Case

Enable approval functionality for a new section

Solution

1. Create a new object for the [Approvals] custom section. The detail object name is generated from the section object name + Visa. For example, for the UsrInnerRequest  section, the object name will be UsrInnerRequestVisa. When creating the object, ensure inheriting from the [BaseVisa] object, add a field for connecting to the section, other parameters should be configured similar to the [OrderVisa] object. 

The UsrInnerRequest object should be managed by records.

2. Enable approval functionality for the custom section page. Namely, migrate all elements from the [OrderPageV2] order page schema to the custom section page by the Visa keyword.

3. Enable approving in the custom section list. Namely, migrate all elements from the [OrderSectionV2] order section list schema to the custom section list schema by the Visa key word.

4. Copy the "Receiving order approval" subprocess and change the Order and Read data parameters, as well as filtering of elements from the [Order] section to the custom section object. The subprocess title should look as follows: section name + VisaBaseSubprocess.

5.Copy the "Order approval" process and change the Order and Read data parameters, element filtering and the link to subprocess for the relevant values. The process title should look as follows: section name + VisaProcess. The elements of sending notifications should be changed for the new sending element.

6. Add a new "[custom section name] Approval process"  system setting with a link to the process specified in item 5. See the setup parameters in the "Order approval process" system setting.

To display approvals on the communication panel:

1. Copy the [OrderVisaNotificationProvider] schema and rename it for the Section name + VisaNotificationProvider. By the Order keyword, replace it in the schema for the name of the custom section object. The titles of the [Orders] section fields should be replaced by the corresponding fields of the custom section.

2. Register the previously added schema with the 0 type by a script in the [Notification Provider] table (the [Lookup] does not enable saving a record with a 0 type):

insert into NotificationProvider (ClassName, Type)
values ('Terrasoft.Configuration.UsrInnerRequestVisaNotificationProvider','0')

 

Like 2

Like

Share

0 comments
Show all comments

1) Create client module

define("GlbHtmlEditModule", ["ext-base", "terrasoft", "HtmlEditModule"], function(Ext, Terrasoft) {
    Ext.define("Terrasoft.controls.GlbHtmlEdit", {
        extend: "Terrasoft.HtmlEdit",
        alternateClassName: "Terrasoft.GlbHtmlEdit",
 
        tplSignature: "<br><div><span style=\"color:#7f2910;\"><i>{0}: {1}</i></span><hr></div>",
 
        signature: false,
 
        setSignature: function(value) {
            if (this.signature === value) {
                return;
            }
            this.signature = value;
        },
 
        onContentDom: function() {
            this.callParent(arguments);
            this.setSignature(false);
            var editor = this.editor;
            if (editor) {
                var editorDocument = this.editor.document;
                if (editorDocument) {
                    var el = editorDocument.$;
                    Ext.EventManager.on(el, "keypress", this.onKeyPress, this);
                }
            }
        },
 
        destroy: function() {
            var editor = this.editor;
            if (editor) {
                var editorDocument = this.editor.document;
                if (editorDocument) {
                    var el = editorDocument.$;
                    Ext.EventManager.removeListener(el, "keypress", this.onKeyPress, this);
                }
            }
            this.callParent(arguments);
        },
 
        onKeyPress: function(e) {
            if (!this.enabled || this.readonly) {
                return;
            }
            if (!this.signature && !e.isNavKeyPress() && !e.isSpecialKey()) {
                this.setSignature(true);
                var editor = this.editor;
                var selection = editor.getSelection();
                var ranges = selection.getRanges();
                var range = ranges[0];
                var currentContact = Terrasoft.SysValue.CURRENT_USER_CONTACT.displayValue;
                var date = new Date();
                var culture = Terrasoft.SysValue.CURRENT_USER_CULTURE ?
                    Terrasoft.SysValue.CURRENT_USER_CULTURE.displayValue : "";
                var signatureHtml = Ext.String.format(this.tplSignature, currentContact,
                    date.toLocaleString(culture));
                var signatureNode = CKEDITOR.dom.element.createFromHtml(signatureHtml);
                range.deleteContents();
                range.select();
                range.insertNode(signatureNode);
                var cursorNode = range.getNextNode();
                range.selectNodeContents(cursorNode);
                selection.selectRanges(ranges);
            }
        }
    });
});

 

2) On the poge add dependency GlbHtmlEditModule and in diff section change className for your field (Example: Field Notes on Contact page):

{
    "operation": "merge",
    "parentName": "NotesControlGroup",
    "propertyName": "items",
    "name": "Notes",
    "values": {
        "className": "Terrasoft.GlbHtmlEdit"
    }
}

 

3) Result

Like 1

Like

Share

0 comments
Show all comments
package cherniak.bpmonline.com;
import java.io.OutputStream;
import java.net.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Attr;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
/**
* OData insert request for bpmonline
*
*/
public class App
{
    private static final String SERVICE_URL = "http://int-                web/Amdocs_T/0/ServiceModel/EntityDataService.svc/";
    private static final String AUTH_URL = "http://int-web/Amdocs_T/ServiceModel/AuthService.svc/Login";
    private static final String DS = "http://schemas.microsoft.com/ado/2007/08/dataservices";
    private static final String DSMD = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
    private static final String ATOM = "http://www.w3.org/2005/Atom";
    public static void main( String[] args ) throws Exception
    {
        CookieManager msCookieManager = new CookieManager();
        CookieHandler.setDefault(msCookieManager);
        if(GetAuthCookie("Supervisor", "Supervisor")) {
            CreateBpmEntityByOdataHttpExample(msCookieManager);
        }
    }
    public static boolean GetAuthCookie(String login, String password) {
        try{
            URL urlAuth = new URL(AUTH_URL);
            HttpURLConnection connection1Auth = (HttpURLConnection) urlAuth.openConnection();
            connection1Auth.setDoOutput(true);
            connection1Auth.setRequestMethod("POST");
            connection1Auth.setRequestProperty("Content-Type","application/json");
            String authJson = String.format("{\"UserName\": \"%s\", \"UserPassword\":\"%s\"}", login, password);
            byte[] outputBytes = authJson.getBytes("UTF-8");
            OutputStream os = connection1Auth.getOutputStream();
            os.write(outputBytes);
            os.close();
            int responseCode = connection1Auth.getResponseCode();
            return responseCode == 200;
        } catch (Exception e) {
            return false;
        }
    }
    public static void CreateBpmEntityByOdataHttpExample(CookieManager manager) {
        try{
            //Create xml document
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();
            Element entry = doc.createElement("entry");
            Attr attrAtom = doc.createAttribute("xmlns");
            attrAtom.setValue(ATOM);
            entry.setAttributeNode(attrAtom);
            doc.appendChild(entry);
 
            Element content = doc.createElement("content");
            Attr attrType = doc.createAttribute("type");
            attrType.setValue("application/xml");
            content.setAttributeNode(attrType);
            entry.appendChild(content);
 
            Element properties = doc.createElement("properties");
            Attr attrMetadata = doc.createAttribute("xmlns");
            attrMetadata.setValue(DSMD);
            properties.setAttributeNode(attrMetadata);
            content.appendChild(properties);
 
            //Set Name of Contact
            Element name = doc.createElement("Name");
            Attr attrProp = doc.createAttribute("xmlns");
            attrProp.setValue(DS);
            name.setAttributeNode(attrProp);
            name.appendChild(doc.createTextNode("Test Person"));
            properties.appendChild(name);
 
            //Set Dear of Contact
            Element dear = doc.createElement("Dear");
            Attr attrOppo = doc.createAttribute("xmlns");
            attrOppo.setValue(DS);
            dear.setAttributeNode(attrOppo);
            dear.appendChild(doc.createTextNode("Mister"));
            properties.appendChild(dear);
 
            doc.setXmlStandalone(true);
 
            //Send insert request
            URL url = new URL(SERVICE_URL + "ContactCollection/");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Accept", "application/atom+xml");
            connection.setRequestProperty("Content-Type","application/atom+xml;type=entry");
 
            //Add BPMCSRF
            for(HttpCookie cookie : manager.getCookieStore().getCookies()) {
                if(cookie.getName().equals("BPMCSRF")) {
                    connection.setRequestProperty("BPMCSRF", cookie.getValue());
                }
            }
            OutputStream os = connection.getOutputStream();
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.transform(new DOMSource(doc), new StreamResult(os));
            os.close();
            int responseCode = connection.getResponseCode();
            System.out.println(responseCode);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

 

Like 0

Like

Share

0 comments
Show all comments

Question

How to implement a search for multiple columns in a section?

For example, in the Contacts section, search by full name and zip code (the column in the Contact object).

Answer

- Launch the mobile app wizard

- Open default workplace (“Main workplace”)

- Go to section settings

- Click "Save"

- Create ClientUnit schema

- Add the following code to it:

Terrasoft.sdk.GridPage.setSearchColumns("Contact", [“Name”, “Zip”]);

- Open MobileApplicationManifestDefaultWorkplace in the Custom package

- Register your schema for the “Contacts” section:

{
    “Models”: {
        “Contact”: {
            "PagesExtensions": [
                "Name_of_the_schema"
            ]
        }
    }
}

 

Like 0

Like

Share

0 comments
Show all comments

Question

Can we set up displaying of a post date in the Feed without specifying "today, yesterday, the day before yesterday"?

Answer

Override the getCreatedOnText() method of the SocialFeedUtilities module. Since you cannot extend modules in bpm'online (you can only replace them completely), create a replacing client module in the custom package and specify SocialFeedUtilities as the parent modue. Copy the text from a similar module in the ESN package (the "Source code and "LESS" tabs) and change the text of the getCreatedOnText method to:

getCreatedOnText: function() {
    var cultureSetting = Terrasoft.Resources.CultureSettings;
    var value = this.get("CreatedOn");
    if (value) {
        var datePart = Ext.Date.dateFormat(value, cultureSetting.dateFormat);
        var timePart = Ext.Date.dateFormat(value, cultureSetting.timeFormat);
        return Ext.String.format("{0} {2} {1}", datePart, timePart,
            FormatUtilsResources.localizableStrings.In);
        }
    return "";
}

At the very beginning of the text, add the dependency of the module from FormatUtilsResources to have access to the FormatUtilsResources.localizableStrings.In localized string of the FormatUtils module:

define("SocialFeedUtilities", ["FormatUtilsResources", "ESNFeedUtils", "ESNFeedModuleResources", 
    "FormatUtils", "ESNConstants", "NetworkUtilities", "ModalBox", "ServiceHelper", "MaskHelper", 
    "performancecountermanager", "css!SocialFeedUtilities"],
    function(FormatUtilsResources, ESNFeedUtils, resources, FormatUtils, ESNConstants, 
        NetworkUtilities, ModalBox, ServiceHelper, MaskHelper, performanceManager) {...

 

Like 0

Like

Share

0 comments
Show all comments

Question

How to add a standard detail to a mobile application and display a specific column in it?

Answer

1. Go to the "Mobile application wizard" (/0/Nui/ViewModule.aspx#SectionModuleV2/SysMobileWorkplaceSection)

2.  Open the required workplace ("DefaultWorkplace" by default) and click the "Set up sections" button.

3. Select the desired section, for example, "Contacts", and press the "Details setup" button

4. Add a detail:

5. Go to the "Configuration" section (/0/WorkspaceExplorerModule.aspx)

6. Add a new "Module" schema type with the name "UsrContactCareerModuleConfig"

7. Write a similar code:

Terrasoft.sdk.GridPage.setPrimaryColumn("ContactCareer", "JobTitle");
Terrasoft.sdk.RecordPage.addColumn("ContactCareer", {
        name: "JobTitle",
        position: 1
    }, "primaryColumnSet");
Terrasoft.sdk.RecordPage.removeColumn("ContactCareer", "Contact", "primaryColumnSet");

Where ContactCareer is the name of the table that corresponds to our detail;

JobTitle - the name of the column you want to display

8. Connect this schema in the "MobileApplicationManifestDefaultWorkplace" mobile application manifest: Find the block of the ContactCareer model and add our UsrContactCareerModuleConfig module to PagesExtensions.

Like that:

 

 

Like 0

Like

Share

0 comments
Show all comments

Symptoms

Bpm'online mobile bug report:

Type: Terrasoft.ServerException

Message: Request for server returned error

Additional info:

{"request":{"id":4,"headers":{"X-Terrasoft-Mobile":"true","Accept":"application/json","Content-Type":"application/json","Authorization":"Cookie","X-Requested-With":"XMLHttpRequest"},"options":{"url":"http://xxxxx.xxxxxxx.xxxxx/0/Services/ProfileService.asmx/Logout","method":"POST","jsonData":{"customData":"","doLogout":"true"},"headers":{"X-Terrasoft-Mobile":"true","Accept":"application/json","Content-Type":"application/json","Authorization":"Cookie"},"disableCaching":false,"scope":{"initialConfig":{"url":"http://xxxxx.xxxxxxx.xxxxx/0/Services/ProfileService.asmx/Logout","method":"POST","jsonData":{"customData":"","doLogout":"true"},"headers":{"X-Terrasoft-Mobile":"true","Accept":"application/json","Content-Type":"application/json","Authorization":"Cookie"},"disableCaching":false},"performanceCounterKey":"86e101ce-533b-4802-941b-56bf73c7b609"}},"async":true},"requestId":4,"status":500,"statusText":"Internal Server Error","responseText":"{\r\n  \"Code\": -1,\r\n  \"Exception\": \"Terrasoft.Core.LicException: The license has expired or inactive\\r\\n  at Terrasoft.Core.UserConnection.CheckLicense()\\r\\n  at Terrasoft.Core.UserConnection.InitializeCurrentUser(String userName, TimeZoneInfo timeZone, String clientIP, String agent, Boolean logSessionStart)\\r\\n  at Terrasoft.Core.UserConnectionFactory.CreateUserConnection(AppConnection appConnection, AuthData authData, String sessionId, String clientIP, String agent, Boolean checkPasswordExpiry)\\r\\n  at Terrasoft.Web.Common.SessionHelper.RecreateUserConnection(AuthData authData)\"\r\n}","responseXML":null,"responseBytes":null}

Cause

The user does not have an active license.

Solution

For correct authorization in the mobile application, it is necessary to distribute the license to the user.

Like 0

Like

Share

0 comments
Show all comments

Question

We want to enable editing the titles in activities of the "email" type. This option is in the disabled mode and we cannot change it on the activity edit page.

Answer

To edit the titles of the "email" type activities, create a "replacing client module" and specify the "EmailPage" schema from a NUI package as a parent object.

Copy the "EmailPage" schema code to the created module. Comment the business rule that is responsible for editing the "Title" field.

Save and publish the module. As a result, the "Title" field will become editable.

 

Like 0

Like

Share

0 comments
Show all comments

Question

I created a section in the Cutom package via section wizard. Can I migrate this section schemas to another custom package? (working at on-demand).

Answer

In the [Configuration] menu, select the "Export to file" action on the [Actions] tab. Select the needed package on the [Packages] tab and perform the "Import from file" action.

Like 1

Like

Share

0 comments
Show all comments

Often, we want to have detail that will contain records which don't exist in DataBase, for this aim we can create "Virtual Detail".

In our development cases we usually create detail which load data from external services. If you want to create this detail you should complete three main steps.

  1. Create virtual object for entities.
  2. Create service which will prepare data collection.
  3. Create virtual detail.
  4. Insert virtual detail into page.

Create POCO object for entities.

You should create virtual object that won't store in DB, but we will display this one in our detail.

Figure 1. POCO object

Create service which will prepare data collection.

In this tutorial I will get data from external WCF service by ProxyClient, you can use another way for this purpose.

In general case you should write configuration service which will prepare data for our detail. My one looks like following:

namespace Terrasoft.Configuration.UsrLocationService
{
    using System;
    using System.Linq;
    using System.IO;
    using System.Text;
    using System.Net;
    using System.Web;
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    using System.Reflection;
    using System.ServiceModel;
    using System.ServiceModel.Activation;
    using System.ServiceModel.Web;
    using Terrasoft.Common;
    using Terrasoft.Core;
    using Terrasoft.Core.Factories;
    using Terrasoft.Core.DB;
    using Terrasoft.Core.Entities;
    using ErrorInfo = Terrasoft.Nui.ServiceModel.DataContract.ErrorInfo;
    using SelectQueryResponse = Terrasoft.Nui.ServiceModel.DataContract.SelectQueryResponse;
    using DataValueType = Terrasoft.Nui.ServiceModel.DataContract.DataValueType;
    using EntityCollection = Terrasoft.Nui.ServiceModel.DataContract.EntityCollection;
    using Newtonsoft.Json;
 
    using System.Globalization;
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class UsrLocationService
    {
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "GetLocations", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public string GetLocations(LocationRequest request) {
            UsrBaseLocationServiceHelper helper = ClassFactory.Get<UsrBaseLocationServiceHelper>();
            var client = helper.ProxyClient;
 
            var result = client.GetLocations(
                string.IsNullOrEmpty(request.AccountName) ? null : request.AccountName,
                string.IsNullOrEmpty(request.AccountNumber) ? null :request.AccountNumber,
                string.IsNullOrEmpty(request.Location) ? null : request.Location,
                null,
                string.IsNullOrEmpty(request.CityName) ? null : request.CityName,
                string.IsNullOrEmpty(request.StateName) ? null : request.StateName,
                string.IsNullOrEmpty(request.Zip) ? null : request.Zip,
                string.IsNullOrEmpty(request.Phone) ? null : request.Phone,
                null,
                null,
                Convert.ToInt32(request.ExcludeDeactivated),
                Convert.ToInt32(request.ExcludeUnassigned)
            );
 
            var response = new UsrLocationResponse();
            response.Message = result.ErrorMessage;
            foreach(var entity in result.Locations)
            {
                response.Locations.Add(
                    new Dictionary<string, object>() {
                        { "Id", Guid.NewGuid() },
                        { "AccountID", entity.AccountID.ToString() },
                        { "AccountName", entity.AccountName },
                        { "Address", entity.Address },
                        { "Country", entity.Country },
                        { "City", entity.City },
                        { "GeneralNbr", entity.GeneralNbr },
                        { "EMail", entity.EMail }
                    }
                );
            }
            var res = new SelectQueryResponse {
                RowsAffected = response.Locations.Count,
                Success = (response.Message == "CallCenterServices.Success." ? true : false),
                Rows = response.Locations,
                RowConfig = RowConfig,
                ErrorInfo = new ErrorInfo {
                    Message = response.Message
                }
            };
 
            return JsonConvert.SerializeObject(res);
        }
 
        public Dictionary<string, object> RowConfig = new Dictionary<string, object> {
            {"Id", new { dataValueType = DataValueType.Guid }},
            {"AccountID", new { dataValueType = DataValueType.Text }},
            {"AccountName", new { dataValueType = DataValueType.Text }},
            {"Address", new { dataValueType = DataValueType.Text }},
            {"Country", new { dataValueType = DataValueType.Text }},
            {"City", new { dataValueType = DataValueType.Text }},
            {"GeneralNbr", new { dataValueType = DataValueType.Text }},
            {"EMail", new { dataValueType = DataValueType.Text }}
        };
    }
 
    [DataContract]
    public class LocationRequest
    {
        [DataMember]
        public string AccountName { get; set; }
        [DataMember]
        public string AccountNumber { get; set; }
        [DataMember]
        public string Location { get; set; }
        [DataMember]
        public string CityName { get; set; }
        [DataMember]
        public string StateName { get; set; }
        [DataMember]
        public string Zip { get; set; }
        [DataMember]
        public string Phone { get; set; }
        [DataMember]
        public bool ExcludeDeactivated { get; set; }
        [DataMember]
        public bool ExcludeUnassigned { get; set; }
    }
 
    [DataContract]
    public class UsrLocationResponse
    {
        public UsrLocationResponse()
        {
            Locations = new EntityCollection();
        }
 
        [DataMember]
        public string Message { get; set; }
        [DataMember]
        public EntityCollection Locations { get; set; }
    }
}

This service should return object which contains EntityCollection.

Inside GetLocations methods after calling proxyсlient you can see how we prepare data:

var response = new UsrLocationResponse();
            response.Message = result.ErrorMessage;
            foreach(var entity in result.Locations)
            {
                response.Locations.Add(
                    new Dictionary<string, object>() {
                        { "Id", Guid.NewGuid() },
                        { "AccountID", entity.AccountID.ToString() },
                        { "AccountName", entity.AccountName },
                        { "Address", entity.Address },
                        { "Country", entity.Country },
                        { "City", entity.City },
                        { "GeneralNbr", entity.GeneralNbr },
                        { "EMail", entity.EMail }
                    }
                );
            }
            var res = new SelectQueryResponse {
                RowsAffected = response.Locations.Count,
                Success = (response.Message == "CallCenterServices.Success." ? true : false),
                Rows = response.Locations,
                RowConfig = RowConfig,
                ErrorInfo = new ErrorInfo {
                    Message = response.Message
                }
            };

Important! Columns should be same in virtual object from first step, foreach statment and RowConfig collection.

 Create virtual detail.

Code of virtual detail is pretty simple. You should just copy it and change few things:

define("UsrLocationSearchResultDetail", ["UsrLocationSearchResultDetailResources"], function(resources) {
    return {
        entitySchemaName: "LocationServicePoco",
        methods: {
            sortColumn: this.Terrasoft.emptyFn,
            loadGridData: this.Terrasoft.emptyFn,
            init: function() {
                this.callParent(arguments);
 
                this.set("IsGridEmpty", true);
                this.set("IsGridDataLoaded", true);
 
                this.loadSearchItems();
            },
            loadSearchItems: function() {
                this.set("MaskId", Terrasoft.Mask.show({timeout: 0}));
                this.set("IsGridEmpty", true);
                this.set("IsGridLoading", true);
                this.set("IsGridDataLoaded", false);
                var serviceConfig = {
                    serviceName: "UsrLocationService",
                    methodName: "GetLocations",
                    timeout: 120000,
                    data: {/*Some input params*/}
                };
                this.callService(serviceConfig, function(responseJson) {
                    this.set("IsGridLoading", false);
                    this.set("IsGridDataLoaded", true);
                    if (!this.Ext.isEmpty(responseJson)) {
                        var response = this.Ext.decode(responseJson);
                        if (response.success) {
                            if (response.rowsAffected > 0) {
                                this.set("IsGridEmpty", false);
                                var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
                                    rootSchemaName: "LocationServicePoco"
                                });
                                esq.parseResponse(response, function(result) {
                                    if (result.success) {
                                        var gridData = this.getGridData();
                                        gridData.clear();
                                        gridData.loadAll(result.collection);
                                        Terrasoft.Mask.hide(this.get("MaskId"));
                                    } else {
                                        this.showInformationDialog(result.errorInfo);
                                        Terrasoft.Mask.hide(this.get("MaskId"));
                                    }
                                }, this);
                            }
                        } else {
                            this.showInformationDialog(response.errorInfo.message);
                            Terrasoft.Mask.hide(this.get("MaskId"));
                        }
                    }
                }, this);
            }
        },
        diff: /**SCHEMA_DIFF*/[
            {
                "operation": "merge",
                "name": "DataGrid",
                "values": {
                    "type": this.Terrasoft.GridType.LISTED,
                    "listedConfig": {
                        "name": "DataGridListedConfig",
                        "items": [
                            {
                                "name": "AccountNumberListedGridColumn",
                                "bindTo": "AccountID",
                                "caption": "Account number",
                                "type": Terrasoft.GridCellType.TEXT,
                                "position": {"column": 1, "colSpan": 2}
                            },
                            {
                                "name": "AccountListedGridColumn",
                                "bindTo": "AccountName",
                                "caption": "Account",
                                "type": Terrasoft.GridCellType.TEXT,
                                "position": {"column": 3, "colSpan": 3}
                            },
                            {
                                "name": "AddressListedGridColumn",
                                "bindTo": "Address",
                                "caption": "Address",
                                "type": Terrasoft.GridCellType.TEXT,
                                "position": {"column": 6, "colSpan": 4}
                            },
                            {
                                "name": "CountryListedGridColumn",
                                "bindTo": "Country",
                                "caption": "Country",
                                "type": Terrasoft.GridCellType.TEXT,
                                "position": {"column": 10, "colSpan": 4}
                            },
                            {
                                "name": "CityListedGridColumn",
                                "bindTo": "City",
                                "caption": "City",
                                "type": Terrasoft.GridCellType.TEXT,
                                "position": {"column": 14, "colSpan": 4}
                            },
                            {
                                "name": "PhoneListedGridColumn",
                                "bindTo": "GeneralNbr",
                                "caption": "Phone",
                                "type": Terrasoft.GridCellType.TEXT,
                                "position": {"column": 18, "colSpan": 3}
                            },
                            {
                                "name": "EmailListedGridColumn",
                                "bindTo": "EMail",
                                "caption": "Email",
                                "type": Terrasoft.GridCellType.TEXT,
                                "position": {"column": 21, "colSpan": 3}
                            }
                        ]
                    },
                    "activeRowActions": [],
                    "activeRowAction": {"bindTo": "onActiveRowAction"},
                    "tiledConfig": {
                        "name": "DataGridTiledConfig",
                        "grid": {"columns": 24, "rows": 1},
                        "items": []
                    }
                }
            }/*,
            {
                "operation": "remove",
                "name": "ToolsButton"
            }*/
        ]/**SCHEMA_DIFF*/
    };
});
  1. You should change entitySchemaName (schema name of your virtual object).
  2. Change parameters of web service calling (service name, method name, timeout and input parameters in data object).
  3. Inside callback of callService function you should change entitySchemaName in ESQ (write schema name of your virtual object).
  4. Change "listedConfig" inside "DataGrid" element of "diff" section. This column config should be same to config in service from step 2.

Insert virtual detail into page.

Just insert created detail into your page.

define("UsrLocationSearchPage", [],
function() {
        return {
            entitySchemaName: "BaseEntity",
            details: /**SCHEMA_DETAILS*/{
                "UsrLocationSearchResultDetail": {
                    "schemaName": "UsrLocationSearchResultDetail"
                }
            }/**SCHEMA_DETAILS*/,
            diff: /**SCHEMA_DIFF*/[
                {
                    "operation": "insert",
                    "name": "UsrLocationSearchResultDetail",
                    "values": {
                        "itemType": 2,
                        "markerValue": "added-detail"
                    },
                    "parentName": "SearchResultContainer",
                    "propertyName": "items",
                    "index": 0
                }
            ]/**SCHEMA_DIFF*/
        };
    });

 

Like 0

Like

Share

7 comments

Could you please send us the screen shot of the data that will be displayed once this function will be called ? 

Hi Tatiana Rogova,

          I followed your guide step by step and receive these error and don't know what going on. How can I find what problem with this? Thanks

Hi Tatiana Rogova,

            I don't know why file js of virtual detail wasn't downloaded after I add it to pre-configuration page. Please help.

Toàn Mai

Hi Toan Mai,

 

Could you please provide a bit more detailed information on your issue? Please send us your code so we could check the request precisely. Look forward to hearing from you!  

 

Regards, 

Anastasiia

 

Hi Anastasiia Markina,

       Because my code locates on many package, I will create a sample package to reproduce my problem. Please wait.

Toàn

Anastasiia Markina,

Hi Anastasiia, Had a follow up question on the virtual detail - 



The sort, sort by and filter features are not available by default on a virtual detail. UI notice that the sort & search on a real detail (One with an object in the database) happens on the server side and the detail just loads the fresh data it receives from the server.



Given this, Is there a way to enable/implement the sort & filter functionality for virtual details as well?



One way would be to override those functions on the detail schema and implement a custom sort & search purely on the client side using JS. But this is practically re-inventing the wheel. Is there a better way to implement the sort & filter? Thanks in advance!



 

M Shrikanth,

 

If you want your custom detail to have sorting, searching, and filtering functions, it's better to use the detail inheritance from the base "BaseGridDetailV2" schema instead. 

 

Thus, you will be able to customize it according to your needs, inherit necessary functionality (like filtering and sorting) and remove unnecessary ones. 

 

Regards,

Anastasiia

Show all comments