Implement a custom UI component based on a classic page
The example is relevant to version 8.0.2 and later.
Display the history of the selected account on the Account timeline tab of the record page of the Requests custom section. The tab is a web component. Implement the web component based on the 7.X Timeline tab displayed on the contact page.
1. Create an app
-
Create a custom
Requests
app based on the Records & business processes template. To do this, follow the procedure in the user documentation: Create a custom app. -
Open the Requests form page page in the workspace of the
Requests
app page.The Requests form page page includes the Name field by default.
-
Add an account field:
-
Add a new field of the Dropdown type to the Freedom UI Designer’s workspace.
-
Click the button on the Freedom UI Designer’s action panel and fill out the field properties in the setup area:
- Set Title to "Account."
- Set Code to "UsrAccount."
- Select "Account" in the Lookup property.
- Clear the Enable adding new values checkbox.
-
-
Add a tab that contains the history of the selected account.
-
Add a new Tabs layout element to the Freedom UI Designer’s workspace.
-
Delete the Tab 2 tab the Requests form page page includes by default.
-
Click the button on the Freedom UI Designer’s action panel and specify "Account timeline" in the Title tab property in the setup area.
-
-
Click Save on the Freedom UI Designer’s action panel.
2. Create a custom web component
-
Go to the Configuration section and select a custom package to add the schema.
-
Click Add → Module on the section list toolbar.
-
Fill out the schema properties in the Module Designer.
- Set Code to "UsrTimelineModule."
- Set Title to "Timeline module."
-
Implement a custom web component.
-
Add the
@creatio-devkit/common
,Base7xViewElement
, andckeditor-base
modules as dependencies to the AMD module declaration.Dependencies of the UsrTimelineModule AMD module/* AMD module declaration. */
define("UsrTimelineModule", ["@creatio-devkit/common", "Base7xViewElement", "ckeditor-base"], function (sdk, Base7xViewElement) {
...
}); -
Declare a custom
UsrTimelineModule
web component class.UsrTimelineModule class declaration/* AMD module declaration. */
define("UsrTimelineModule", ["@creatio-devkit/common", "Base7xViewElement", "ckeditor-base"], function (sdk, Base7xViewElement) {
/* Class declaration. */
class UsrTimelineModule extends Base7xViewElement {
set primaryColumnValue(value) {
this._primaryColumnValue = value;
this._init();
}
get primaryColumnValue() {
return this._primaryColumnValue;
}
set entitySchemaName(value) {
this._entitySchemaName = value;
this._init();
}
get entitySchemaName() {
return this._entitySchemaName;
}
set cardSchemaName(value) {
this._cardSchemaName = value;
this._init();
}
get cardSchemaName() {
return this._entitySchemaName;
}
constructor() {
super("Timeline");
}
_init() {
if (this._primaryColumnValue && this._cardSchemaName && this._entitySchemaName) {
this.initContext(() => {
this._moduleId = this.sandbox.id + "_UsrTimelineModule";
this.sandbox.subscribe("GetColumnsValues", (attributeNames) => this._getColumnValues(attributeNames), null, [this._moduleId]);
this.sandbox.subscribe("GetEntityInfo", () => this._getEntityInfo(), null, [this._moduleId]);
this._loadTimelineSchemaModule();
});
}
}
_loadTimelineSchemaModule() {
this._moduleId = this.sandbox.loadModule("BaseSchemaModuleV2", {
id: this._moduleId,
renderTo: this._renderTo,
instanceConfig: {
schemaName: "TimelineSchema",
isSchemaConfigInitialized: true,
useHistoryState: false,
showMask: true,
parameters: {
viewModelConfigDiff: {
"CardSchemaName": this._cardSchemaName,
"ReferenceSchemaName": this._entitySchemaName,
"InitialConfig": {
"entities": []
}
},
},
}
});
}
_getColumnValues(attributeNames) {
const values = {};
attributeNames?.forEach((attributeName) => {
switch (attributeName) {
case "Id":
values[attributeName] = this._primaryColumnValue?.value;
break;
case "Name":
values[attributeName] = this._primaryColumnValue?.displayValue;
break;
default: break;
}
});
return values;
}
_getEntityInfo() {
return {
entitySchemaName: this._entitySchemaName,
primaryColumnValue: this._primaryColumnValue?.value,
primaryDisplayColumnValue: this._primaryColumnValue?.displayValue
};
}
getMessages() {
const messages = super.getMessages();
return Object.assign(messages, {
"GetColumnsValues": {
mode: Terrasoft.MessageMode.PTP,
direction: Terrasoft.MessageDirectionType.SUBSCRIBE
},
"GetEntityInfo": {
mode: Terrasoft.MessageMode.PTP,
direction: Terrasoft.MessageDirectionType.SUBSCRIBE
}
});
}
disconnectedCallback() {
this.sandbox.unloadModule(this._moduleId, this._renderTo);
}
}
...
}); -
Register the
UsrTimelineModule
web component on the page.Register the UsrTimelineModule web component/* AMD module declaration. */
define("UsrTimelineModule", ["@creatio-devkit/common", "Base7xViewElement", "ckeditor-base"], function (sdk, Base7xViewElement) {
...
/* Web component registration. */
customElements.define('usr-timeline', UsrTimelineModule);
...
}); -
Register the
usr-timeline
web component as a visual element.usr-timeline web component registration/* AMD module declaration. */
define("UsrTimelineModule", ["@creatio-devkit/common", "Base7xViewElement", "ckeditor-base"], function (sdk, Base7xViewElement) {
...
/* Register a web component as a visual element. */
sdk.registerViewElement({
type: 'usr.Timeline',
selector: 'usr-timeline',
inputs: {
primaryColumnValue: {},
cardSchemaName: {},
entitySchemaName: {}
}
});
});
-
-
Click Save on the Module Designer’s toolbar.
3. Add the custom web component to the Freedom UI page
-
Open the
UsrRequests_FormPage
schema of the Freedom UI Requests form page page in the Configuration section. -
Click the button on the Freedom UI Designer’s action panel. This opens the source code of the Freedom UI page.
-
Add the custom web component.
-
Add the
UsrTimelineModule
module of the custom web component as a dependency to the AMD module declaration.Dependencies of the UsrRequests_FormPage AMD module/* AMD module declaration. */
define("UsrRequests_FormPage", /**SCHEMA_DEPS*/["UsrTimelineModule"]/**SCHEMA_DEPS*/, function/**SCHEMA_ARGS*/()/**SCHEMA_ARGS*/ {
...
}); -
Add the configuration object of the
UsrTimelineModule
module with the custom web component to theviewConfigDiff
schema section.viewConfigDiff schema sectionviewConfigDiff: /**SCHEMA_VIEW_CONFIG_DIFF*/[
...,
{
"operation": "insert",
"name": "Timeline_qwerty",
"values": {
"type": "usr.Timeline",
"layoutConfig": {
"column": 1,
"row": 1,
"colSpan": 12,
"rowSpan": 8
},
"primaryColumnValue": "$UsrAccount",
"cardSchemaName": "AccountPageV2",
"entitySchemaName": "Account"
},
"parentName": "GridContainer_qaocexw",
"propertyName": "items",
"index": 0
},
...
]/**SCHEMA_VIEW_CONFIG_DIFF*/,
-
-
Click Save on the Client Module Designer’s toolbar.
Outcome of the example
To view the outcome of the example:
- Open the
Requests
app page and click Run app. - Click New on the
Requests
app toolbar. - Enter "Request’s name" in the Name field.
- Select an account in the Account field, for example, "Accom."
As a result, Creatio will display the Account timeline tab of the selected "Accom" account on the request page.
Freedom UI Designer will display a stub in place of the custom web component.
Source codes
- UsrTimelineModule
- UsrRequests_FormPage
/* AMD module declaration. */
define("UsrTimelineModule", ["@creatio-devkit/common", "Base7xViewElement", "ckeditor-base"[, function(sdk, Base7xViewElement) {
/* Class declaration. */
class UsrTimelineModule extends Base7xViewElement {
set primaryColumnValue(value) {
this._primaryColumnValue = value;
this._init();
}
get primaryColumnValue() {
return this._primaryColumnValue;
}
set entitySchemaName(value) {
this._entitySchemaName = value;
this._init();
}
get entitySchemaName() {
return this._entitySchemaName;
}
set cardSchemaName(value) {
this._cardSchemaName = value;
this._init();
}
get cardSchemaName() {
return this._entitySchemaName;
}
constructor() {
super("Timeline");
}
_init() {
if (this._primaryColumnValue && this._cardSchemaName && this._entitySchemaName) {
this.initContext(() => {
this._moduleId = this.sandbox.id + "_UsrTimelineModule";
this.sandbox.subscribe("GetColumnsValues", (attributeNames) => this._getColumnValues(attributeNames), null, [this._moduleId]);
this.sandbox.subscribe("GetEntityInfo", () => this._getEntityInfo(), null, [this._moduleId]);
this._loadTimelineSchemaModule();
});
}
}
_loadTimelineSchemaModule() {
this._moduleId = this.sandbox.loadModule("BaseSchemaModuleV2", {
id: this._moduleId,
renderTo: this._renderTo,
instanceConfig: {
schemaName: "TimelineSchema",
isSchemaConfigInitialized: true,
useHistoryState: false,
showMask: true,
parameters: {
viewModelConfigDiff: {
"CardSchemaName": this._cardSchemaName,
"ReferenceSchemaName": this._entitySchemaName,
"InitialConfig": {
"entities": []
}
},
},
}
});
}
_getColumnValues(attributeNames) {
const values = {};
attributeNames?.forEach((attributeName) => {
switch (attributeName) {
case "Id":
values[attributeName] = this._primaryColumnValue?.value;
break;
case "Name":
values[attributeName] = this._primaryColumnValue?.displayValue;
break;
default: break;
}
});
return values;
}
_getEntityInfo() {
return {
entitySchemaName: this._entitySchemaName,
primaryColumnValue: this._primaryColumnValue?.value,
primaryDisplayColumnValue: this._primaryColumnValue?.displayValue
};
}
getMessages() {
const messages = super.getMessages();
return Object.assign(messages, {
"GetColumnsValues": {
mode: Terrasoft.MessageMode.PTP,
direction: Terrasoft.MessageDirectionType.SUBSCRIBE
},
"GetEntityInfo": {
mode: Terrasoft.MessageMode.PTP,
direction: Terrasoft.MessageDirectionType.SUBSCRIBE
}
});
}
disconnectedCallback() {
this.sandbox.unloadModule(this._moduleId, this._renderTo);
}
}
/* Web component registration. */
customElements.define('usr-timeline', UsrTimelineModule);
/* Register a web component as a visual element. */
sdk.registerViewElement({
type: 'usr.Timeline',
selector: 'usr-timeline',
inputs: {
primaryColumnValue: {},
cardSchemaName: {},
entitySchemaName: {}
}
});
return Terrasoft.UsrTimelineModule;
});
/* AMD module declaration. */
define("UsrRequests_FormPage", /**SCHEMA_DEPS*/["UsrTimelineModule"]/**SCHEMA_DEPS*/, function/**SCHEMA_ARGS*/()/**SCHEMA_ARGS*/ {
return {
viewConfigDiff: /**SCHEMA_VIEW_CONFIG_DIFF*/[
{
"operation": "insert",
"name": "UsrName",
"values": {
"layoutConfig": {
"column": 1,
"row": 1,
"colSpan": 1,
"rowSpan": 1
},
"type": "crt.Input",
"label": "$Resources.Strings.UsrName",
"control": "$UsrName"
},
"parentName": "LeftAreaProfileContainer",
"propertyName": "items",
"index": 0
},
{
"operation": "insert",
"name": "UsrAccount",
"values": {
"layoutConfig": {
"column": 1,
"row": 2,
"colSpan": 1,
"rowSpan": 1
},
"type": "crt.ComboBox",
"loading": false,
"control": "$UsrAccount",
"label": "$Resources.Strings.UsrAccount",
"labelPosition": "auto",
"listActions": [],
"showValueAsLink": true,
"placeholder": "",
"controlActions": []
},
"parentName": "LeftAreaProfileContainer",
"propertyName": "items",
"index": 1
},
{
"operation": "insert",
"name": "TabPanel_grveew2",
"values": {
"layoutConfig": {
"column": 1,
"row": 1,
"colSpan": 2,
"rowSpan": 1
},
"type": "crt.TabPanel",
"items": [],
"styleType": "default",
"bodyBackgroundColor": "primary-contrast-500",
"tabTitleColor": "auto",
"selectedTabTitleColor": "auto",
"headerBackgroundColor": "auto",
"underlineSelectedTabColor": "auto"
},
"parentName": "ControlGroupContainer",
"propertyName": "items",
"index": 0
},
{
"operation": "insert",
"name": "AccountTimeline",
"values": {
"type": "crt.TabContainer",
"items": [],
"caption": "#ResourceString(AccountTimeline_caption)#",
"iconPosition": "only-text"
},
"parentName": "TabPanel_grveew2",
"propertyName": "items",
"index": 0
},
{
"operation": "insert",
"name": "GridContainer_qaocexw",
"values": {
"type": "crt.GridContainer",
"items": [],
"rows": "minmax(32px, max-content)",
"columns": [
"minmax(32px, 1fr)",
"minmax(32px, 1fr)"
],
"gap": {
"columnGap": "large",
"rowGap": 0
}
},
"parentName": "AccountTimeline",
"propertyName": "items",
"index": 0
},
{
"operation": "insert",
"name": "Timeline_qwerty",
"values": {
"type": "usr.Timeline",
"layoutConfig": {
"column": 1,
"row": 1,
"colSpan": 12,
"rowSpan": 8
},
"primaryColumnValue": "$UsrAccount",
"cardSchemaName": "AccountPageV2",
"entitySchemaName": "Account"
},
"parentName": "GridContainer_qaocexw",
"propertyName": "items",
"index": 0
}
]/**SCHEMA_VIEW_CONFIG_DIFF*/,
viewModelConfigDiff: /**SCHEMA_VIEW_MODEL_CONFIG*/{
"attributes": {
"UsrName": {
"modelConfigDiff": {
"path": "PDS.UsrName"
}
},
"Id": {
"modelConfigDiff": {
"path": "PDS.Id"
}
},
"UsrAccount": {
"modelConfigDiff": {
"path": "PDS.UsrAccount"
}
}
}
}/**SCHEMA_VIEW_MODEL_CONFIG*/,
modelConfigDiff: /**SCHEMA_MODEL_CONFIG*/{
"dataSources": {
"PDS": {
"type": "crt.EntityDataSource",
"config": {
"entitySchemaName": "UsrRequests"
},
"scope": "page"
}
},
"primaryDataSourceName": "PDS"
}/**SCHEMA_MODEL_CONFIG*/,
handlers: /**SCHEMA_HANDLERS*/[]/**SCHEMA_HANDLERS*/,
converters: /**SCHEMA_CONVERTERS*/{}/**SCHEMA_CONVERTERS*/,
validators: /**SCHEMA_VALIDATORS*/{}/**SCHEMA_VALIDATORS*/
};
});