Anyone can help me to enable live update data like in web application and implement in mobile app? or like Refresh button on the top right corner dashboard section at mobile app?

need to be implement in this preview page:

So the users didn't should click Back button and choose the record again. Thank you.

Like 2

Like

1 comments

Hello,

This community post regarding data refresh may be helpful to you.

Best regards,
Antonii.

Show all comments
mobile
mobile application
Mobile_Creatio
Mobile app

Hello guys,

 

How to make the preview page of all sections in mobile apps readonly?

 


For example, when we open the opportunity section then we open one of the opportunity data, all fields that appear should be readonly. For now we can change the data without having to click the edit button, we should have to click the edit button first to edit the data.

 

Please help to solve the problem, thank you.

Like 3

Like

3 comments

Hi Agus Sulistiawan

If you want to make the mobile field read only, you can go for business rule on the client module it might be work.
For example:
If Name column filled in then Make it has read only.
 

Prem Kumar,

Hi Prem Kumar,

 

Yes, to make the field read-only, you can set business rules in the related client module.


But this is a different case, I want to make all fields in the preview page of mobile apps read-only. 

 

The question is, how to make all fields on the preview page of mobile apps read-only.

For anyone who wants to implement the case above, you can follow the guidelines at this link:

 

https://community.creatio.com/questions/mobile-app-hide-field-preview-page-and-show-edit-page

 

I have completed the case by following the guide

Show all comments

How can you set custom field e.g. UsrSecondType on Account as readonly in Mobile app with Freedom UI?

Like 0

Like

1 comments

If you go to Configurations and search for the object, open it on the left hand side you see business rules then you put conditions in a way where a field that is required is set to filled in and the field that you want read only select that. 


Here color is the field you want to make read only and Job number is a required filled. 

Show all comments
Mobile_Creatio
caselifecycle

Hello, i want to ask about how to implement code on life cycle Initialized on Mobile Creatio. On Web version, i can use onInitiliazed function, but on mobile i didnt find any possible way to do so. 

In my case, i need to get current month everytime user open the page. 

Anyone can help? 

Like 0

Like

3 comments

Hello,

 

As was stated here, the analog of the onEntityInitialized method from the desktop version is the onLoadRecord method in the mobile application. It should be overridden in the Controller of the corresponded edit page of the mobile application. 

Oleg Drobina,

Hi Oleg Drobina, thanks for answer my question. 
Can i have example of onLoadRecord code, i still have no idea how to use it. 
Thanks

Yosua Aleksander Thanos, 

Hello! 

Here is an example of the controller for the PharmaMobileActivityEditPage, you may modify it according to your business task:

/* globals Activity: false */
/* globals ActivityCategory: false */
Terrasoft.LastLoadedPageData = {
	controllerName: "Terrasoft.configuration.controller.PharmaMobileActivityEditPage",
	viewXType: "fieldforceactivityeditpageview"
};
 
Ext.define("Terrasoft.configuration.controller.PharmaMobileActivityEditPage", {
	alternateClassName: "PharmaMobileActivityEditPage.Controller",
	extend: "FieldForceActivityEditPage.Controller",
 
	statics: {
		Model: Activity
	},
 
	/**
	 * @private
	 */
	createPromotedProducts: function(config) {
		var record = config.records.pop();
		if (!record) {
			Ext.callback(config.success, config.scope);
			return;
		}
		var product = record.get("Product");
		if (!product) {
			this.createPromotedProducts(config);
			return;
		}
		var failureFn = function(exception) {
			Ext.callback(config.failure, config.scope, [exception]);
		};
		var modelName = "ActivityPromProduct";
		var model = Ext.ClassManager.get(modelName);
		model.createWithDefaultValues(function(newRecord) {
			newRecord.set("Activity", config.activityId);
			newRecord.set("Product", product);
			newRecord.save({
				isCancelable: false,
				queryConfig: Ext.create("Terrasoft.QueryConfig", {
					modelName: modelName,
					columns: ["Activity", "Product"]
				}),
				success: function() {
					this.createPromotedProducts(config);
				},
				failure: failureFn
			}, this);
		}, failureFn, this, {isCancelable: false});
	},
 
	/**
	 * @private
	 */
	getPromotedProducts: function(config) {
		var filters = Ext.create("Terrasoft.Filter", {
			property: "Contact",
			value: config.contactId
		});
		var columns = ["Product"];
		Terrasoft.DataUtils.loadRecords({
			modelName: "PromotedProduct",
			filters: filters,
			columns: columns,
			success: function(records) {
				Ext.callback(config.success, config.scope, [records]);
			},
			failure: function(exception) {
				Ext.callback(config.failure, config.scope, [exception]);
			},
			scope: this
		});
	},
 
	/**
	 * @private
	 */
	createNosologiesByProducts: function(config) {
		var filters = Ext.create("Terrasoft.Filter", {
			property: "Product",
			funcType: Terrasoft.FilterFunctions.In,
			funcArgs: config.productIds
		});
		var failureFn = function(exception) {
			Ext.callback(config.failure, config.scope, [exception]);
		};
		Terrasoft.DataUtils.loadRecords({
			modelName: "NosologyInProduct",
			filters: filters,
			columns: ["Nosology"],
			success: function(records) {
				this.createNosologyInActivity({
					activityId: config.activityId,
					records: records,
					addedNosologies: [],
					success: function() {
						Ext.callback(config.success, config.scope);
					},
					failure: failureFn,
					scope: this
				});
			},
			failure: failureFn,
			scope: this
		});
	},
 
	/**
	 * @private
	 */
	createNosologyInActivity: function(config) {
		var record = config.records.pop();
		if (!record) {
			Ext.callback(config.success, config.scope);
			return;
		}
		var nosology = record.get("Nosology");
		var nosologyId = nosology ? nosology.getId() : null;
		if (nosologyId === null || Ext.Array.contains(config.addedNosologies, nosologyId)) {
			this.createNosologyInActivity(config);
			return;
		}
		var failureFn = function(exception) {
			Ext.callback(config.failure, config.scope, [exception]);
		};
		var modelName = "NosologyInActivity";
		var model = Ext.ClassManager.get(modelName);
		model.createWithDefaultValues(function(newRecord) {
			newRecord.set("Activity", config.activityId);
			newRecord.set("Nosology", nosology);
			newRecord.save({
				isCancelable: false,
				queryConfig: Ext.create("Terrasoft.QueryConfig", {
					modelName: modelName,
					columns: ["Activity", "Nosology"]
				}),
				success: function() {
					config.addedNosologies.push(nosologyId);
					this.createNosologyInActivity(config);
				},
				failure: failureFn
			}, this);
		}, failureFn, this, {isCancelable: false});
	},
 
	/**
	 * @private
	 */
	fillVisitToDoctorDetails: function(config) {
		var failureFn = function(exception) {
			Ext.callback(config.failure, config.scope, [exception]);
		};
		this.getPromotedProducts({
			contactId: config.contactId,
			success: function(promotedProducts) {
				this.createPromotedProducts({
					activityId: config.activityId,
					records: Ext.clone(promotedProducts),
					success: function() {
						var productIds = [];
						for (var i = 0, ln = promotedProducts.length; i < ln; i++) {
							var productId = promotedProducts[i].get("Product.Id");
							if (productId) {
								productIds.push(productId);
							}
						}
						if (productIds.length === 0) {
							Ext.callback(config.success, config.scope);
							return;
						}
						this.createNosologiesByProducts({
							activityId: config.activityId,
							productIds: productIds,
							success: function() {
								Ext.callback(config.success, config.scope);
							},
							failure: failureFn,
							scope: this
						});
					},
					failure: failureFn,
					scope: this
				});
			},
			failure: failureFn,
			scope: this
		});
	},
 
	/**
	 * @inheritdoc
	 * @protected
	 * @overridden
	 */
	copyProductsFromAccount: function(config) {
		var activity = config.activity;
		var categoryId = activity.get("ActivityCategory.Id");
		if (categoryId === Terrasoft.Configuration.ActivityCategory.PharmacyVisit) {
			this.callParent(arguments);
		} else {
			Ext.callback(config.success, config.scope);
		}
	},
 
	/**
	 * @inheritdoc
	 * @protected
	 * @overridden
	 */
	onLoadRecord: function(record) {
		var detailConfig = this.getDetailConfig();
		if (record.phantom && detailConfig && record.get("Type.Id") === Terrasoft.Configuration.ActivityTypes.Visit) {
			var categoryId;
			switch (detailConfig.parentColumnName) {
				case "Account":
					categoryId = Terrasoft.Configuration.ActivityCategory.PharmacyVisit;
					break;
				case "Contact":
					categoryId = Terrasoft.Configuration.ActivityCategory.DoctorVisit;
					break;
				default:
					categoryId = null;
					break;
			}
			if (categoryId) {
				var activityCategory = ActivityCategory.Store.getById(categoryId);
				record.set("ActivityCategory", activityCategory);
			}
		}
		this.callParent(arguments);
		var pageHistoryItem = this.getPageHistoryItem();
		var rawConfig = pageHistoryItem.getRawConfig();
		if (rawConfig.focusColumn) {
			setTimeout(function() {
				var field = this.getFieldByColumnName(rawConfig.focusColumn);
				if (!field) {
					return;
				}
				if ("getPicker" in field) {
					var picker = field.getPicker();
					picker.show();
				} else {
					field.focus();
				}
			}.bind(this), 50);
		}
	},
 
	/**
	 * @inheritdoc
	 * @protected
	 * @overridden
	 */
	completeDataSaving: function() {
		var args = arguments;
		var record = this.record;
		var categoryId = record.get("ActivityCategory.Id");
		var contactId = record.get("Contact.Id");
		if (this.isNewVisit && categoryId === Terrasoft.Configuration.ActivityCategory.DoctorVisit && contactId) {
			var activityId = record.getPrimaryColumnValue();
			this.fillVisitToDoctorDetails({
				activityId: activityId,
				contactId: contactId,
				success: function() {
					var parent = Terrasoft.configuration.controller.PharmaMobileActivityEditPage.superclass;
					parent.completeDataSaving.apply(this, args);
				},
				failure: function(exception) {
					Terrasoft.Mask.hide({force: true});
					Terrasoft.MessageBox.showException(exception);
				},
				scope: this
			});
		} else {
			this.callParent(args);
		}
	},
 
	/**
	 * @inheritdoc
	 * @protected
	 * @overridden
	 */
	getCategoryId: function() {
		var activityRecord = this.record;
		var category = activityRecord.get("ActivityCategory");
		return category ? category.get("Id") : null;
	}
 
});
Show all comments

Hi Community, 

 

I have written a business rule that, when a boolean field has been set to true in the mobile app, stores the current timestamp in another separate date/time field: 

 

Terrasoft.sdk.Model.addBusinessRule("Activity", {
    name: "SetTimestampOnCheckForTriggeredField",
    ruleType: Terrasoft.RuleTypes.Custom,
    triggeredByColumns: [
        "InnEndSiteVisitCheck", "InnEndTravelInCheck", "InnEndTravelOutCheck",
        "InnStartSiteVisitCheck", "InnStartTravelInCheck", "InnStartTravelOutCheck"
    ],
    events: [Terrasoft.BusinessRuleEvents.ValueChanged],
 
    executeFn: function(record, rule, column, customData, callbackConfig) {
        // Mapping of boolean fields to their corresponding date-time fields
        var fieldMapping = {
            "InnEndSiteVisitCheck": "InnEndSiteVisitTime",
            "InnEndTravelInCheck": "InnEndTravelInTime",
            "InnEndTravelOutCheck": "InnEndTravelOutTime",
            "InnStartSiteVisitCheck": "InnStartSiteVisitTime",
            "InnStartTravelInCheck": "InnStartTravelInTime",
            "InnStartTravelOutCheck": "InnStartTravelOutTime"
        };
 
        // Get the boolean value of the triggered field
        var isCheckTrue = record.get(column);
 
        // Check if the boolean field is true
        if (isCheckTrue && fieldMapping[column]) {
            // Set the corresponding date-time field to the current date/time
            var currentDateTime = new Date();
            record.set(fieldMapping[column], currentDateTime);
        }
 
        // Asynchronous callback to indicate the rule has been processed
        Ext.callback(callbackConfig.success, callbackConfig.scope, [true]);
    }
});

 

I now want to be able to show a warning message that gives an option to 'cancel' or 'confirm' when a user attempts to set one of these booleans to false. 

 

The box would need to be shown after an attempt to change the booleans value, halting this action until confirmed  - if the action is not prevented before confirmation and the 'cancel' option merely reverts the boolean to being true, the old timestamp would be lost with the new value being representative of the time of cancellation (which is not what I desire).

 

The following post presents a similar requirement: Pop-up with options in mobile application | Community Creatio

 

However, guidance given points to a push notification (which I can't envision helping as I require an option in the app that temporarily halts the setting of the boolean to false), or to use Terrasoft.MessageBox.showMessage, which from what I can tell can only produce a message box (no option to cancel or confirm). 

 

I have also thought about writing individual rules that set each field to be disabled once it has been checked:

 

// Disable the InnEndSiteVisitCheck field after it is checked
Terrasoft.sdk.Model.addBusinessRule("Activity", {
    name: "DisableInnEndSiteVisitCheck",
    ruleType: Terrasoft.RuleTypes.Activation,
    triggeredByColumns: ["InnEndSiteVisitCheck"],
    events: [Terrasoft.BusinessRuleEvents.Load, Terrasoft.BusinessRuleEvents.ValueChanged],
    conditionalColumns: [
        { name: "InnEndSiteVisitCheck", value: true }
    ],
    dependentColumnNames: ["InnEndSiteVisitCheck"]
});

 

However, this is not as flexible as I would want as users may set field values to true by mistake. Even then, the rule I have written does not seem to work as I get a server error when syncing in the mobile app after adding it - perhaps this is because two rules are initiated by the same event? 

Any help on this would be greatly appreciated, thanks in advance!

Like 1

Like

2 comments
Best reply

Hello,

 

Terrasoft.MessageBox also contains the showConfirmation method that can be called to show the confirmation box:

Also you can specify the callback function that will be called upon clicking the "confirm" button (using the yesCallback function inside the object that is passed as an argument into the showConfirmation method or "negative" button (the noCallback function should be created). So you can use it in your development.

Hello,

 

Terrasoft.MessageBox also contains the showConfirmation method that can be called to show the confirmation box:

Also you can specify the callback function that will be called upon clicking the "confirm" button (using the yesCallback function inside the object that is passed as an argument into the showConfirmation method or "negative" button (the noCallback function should be created). So you can use it in your development.

Hi Oleg,

 

Thanks for your reply, this has helped to develop a solution!

Show all comments
mobile
Buttons
client_module
Mobile_Creatio
8.0

Hi there,

 

I am trying to create a mobile app which has custom buttons which, when pressed, record a timestamp. I have created a new workplace in the mobile application wizard and have added the section where I want to include these buttons. When I generate this section, four client modules are created as shown in the image attached. Can I configure these custom buttons in one of these client modules? Some documentation recommends configuration in MobileFUI... client modules but I have no MobileFUI client modules for my new section.
 

 

Thanks 

Like 1

Like

2 comments

Hello,
The process of adding a new button in the mobile app involves creating your own remote module, basically, the list of things you need to do is following:

  1. 1) Create TypeScript project for remote module.
  2. 2) Create a custom request in remote module.
  3. 3) Create custom request handlers using remote module.
  4. 4) Register handler in remote module.
  5. 5) Build project and upload changes to Creatio.
  6. 6) Add button to the page using metadata.
  7. 7) Check functionality.
  8. Also, you need to add and enable EnableMobileSDK feature in the features section.
    An example of adding a custom module can be found in this article. In your case, the code of the remote module should look like this:
  9. import {
    	BaseRequest,
    	BaseRequestHandler,
    	CrtModule,
    	CrtRequestHandler,
    	Logger,
    	CrtRequest,
    	ModalPresenter,
    	bootstrapCrtModule,
    	DoBootstrap,
    } from '@creatio/mobile-common';
     
    @CrtRequest({
    	type: 'crt.MyButtonRequest',
    })
    export class MyButtonRequest extends BaseRequest {
    	public message?: string;
    }
     
    @CrtRequestHandler({
    	requestType: 'crt.MyButtonRequest',
    	type: 'usr.MyButtonRequest',
    	scopes: ['UsrMobileUsrUserModuleRecordPageSettingsDefaultWorkplace_Root'],
    })
    export class UsrMyButtonRequestHandler extends BaseRequestHandler<MyButtonRequest> {
    	public async handle(request: BaseRequest): Promise<unknown> {
    		var message: string | undefined = (request as MyButtonRequest).message;
    		if (message) {
    			Logger.console('Request message: ' + message);
    			ModalPresenter.showSnackBar('Message title', message);
    		}
    		return this.next?.handle(request);
    	}
    }
     
    @CrtModule({
    	requestHandlers: [
    		UsrMyButtonRequestHandler,
    	],
    })
    export class UsrModule implements DoBootstrap {
    	bootstrap(): void {
    		bootstrapCrtModule('UsrModule', UsrModule);
    	}
    }

The difference with the article above is a way to add a button. In order to do so in one of the schemas you showed (depending on where you want to locate a button) you need to add a code of the button to a viewConfigDiff:

{
	"operation": "insert",
	"name": "settings",
	"values": {
		"entitySchemaName": "UsrUserModule",
		"details": [],
		"columnSets": [],
		"localizableStrings": {
			"SocialMessageDetailCaptionUsrUserModule_caption": "Feed",
			"AttachmentsDetailCaptionUsrUserModule_caption": "Attachments",
			"primaryColumnSetUsrUserModule_caption": "General information"
		},
		"settingsType": "RecordPage",
		"operation": "insert",
        "viewConfigDiff": "[{\"operation\": \"insert\", \"name\": \"MyButton\", \"parentName\": \"UsrUserModule_PrimaryTab_Body_primaryColumnSet\", \"propertyName\":\"items\", \"values\": {\"type\":\"crt.Button\",\"caption\": \"Click here\", \"color\":\"primary\",\"clicked\":{\"request\": \"crt.MyButtonRequest\", \"params\": { \"message\": \"Some test message\" }}}}]"
	}
}

Dmytro Vovchenko,

Thank you!

Show all comments
businessrules
Mobile_Creatio
8.0

Hello,
I have a slightly urgent question on how to get Address from Account lookup
the code lookslike this
Terrasoft.sdk.Model.addBusinessRule("Activity", {

  name: "LatLongPreFilled",

  ruleType: Terrasoft.RuleTypes.Custom,

  triggeredByColumns: ["Usrcheck_in"],

  events: [

    Terrasoft.BusinessRuleEvents.ValueChanged,

    Terrasoft.BusinessRuleEvents.Save,

  ],

  executeFn: function (model, rule, column, customData, callbackConfig) {

    if (navigator.geolocation) {

      navigator.geolocation.getCurrentPosition(

        function (position) {

          model.set("Usrcheck_in_longitude", position.coords.longitude, true);

          model.set("Usrcheck_in_latitude", position.coords.latitude, true);


 

          var account = model.get("Account").get("Address");


 

          alert(account);

          Ext.callback(callbackConfig.success, callbackConfig.scope);

        },


 

        function (error) {

          alert("Geolocation failed: " + error.message);

          Ext.callback(callbackConfig.success, callbackConfig.scope);

        }

      );

    } else {

      alert("Geolocation is not supported by this browser.");

      Ext.callback(callbackConfig.success, callbackConfig.scope);

    }

  },

});


i use this: var account = model.get("Account").get("Address"); 
but when i test it, displayed on an alert it says "undefined", but this model.get("Account").get("Id"); or model.get("Account").get("Name"); works fine.
Can anyone help me out? 

Thank you.  

Like 1

Like

3 comments

Hello,

 

Please check if the Address column is present in the SyncColumns array of the Account entity in the ModelDataImportConfig array of the mobile application manifest. It seems that the column is not synced so you receive undefined in the debugger.

Oleg Drobina,


Hi Oleg,
thanks for the reply,

should i add manually on Mobile manifest file or via Mobile Application Wizard?
PS: i don't use debugger like console.log, i use javascript's alert function since i use iOS and i have no clue on how to debug mobile apps on a smartphone, especially iOS.

Yanuar Adinagoro Vishnu Saputro,

 

It can be either manually or you can add the Address column to the account edit page and the column should be added to the manifest automatically in this case.

Show all comments
mobile application
#mobileapp
Mobile_Creatio
8.0

It is possible to change the name of the mobile app?

 

Can be rename with the name of the company instead of "Creatio"?

 

Thanks 

Like 0

Like

2 comments

Hello,

 

While it is not possible to change the name of the mobile app directly, you can use Mobile Branding to customize your mobile application.

 

You can find more information about Mobile app Branding in this article: https://academy.creatio.com/docs/8.x/dev/development-on-creatio-platfor…

Thanks for the tip

Show all comments
mobile application
Mobile_Creatio
map
8.0

Hi Team,

 

We have installed the Field Management (Open Street Map) in our instance map configurations is working as we expected in web app but same thing we configured in the Mobile app, fields are displaying but the map UI is not showing in mobile.

And we have tried to install the Field Sales connector, DB error occurred while installing please help us to achieve the Mobile map configuration.

 

Error log on Filed Sales:

 

2024-09-23 14:09:41,557 Error occurred while installing data "SysModuleInWorkplace" in package "FieldForce". UId 5f69e597-9acb-4852-9f3d-e4d278c7b02b: The UPDATE statement conflicted with the FOREIGN KEY constraint "FKd5jrT2KFY0lXcOnqZCi4dxhomfE". The conflict occurred in database "Creatio8DB_GL_250424", table "dbo.SysModule", column 'Id'.

The statement has been terminated.

 

Thanks,

Prem

Like 0

Like

4 comments

You look like to be dealing with two different problems. It can be a platform-specific usability or setup problem with the mobile app map user interface. Examine any settings unique to mobile devices and see if the mobile map feature is properly supported. Regarding the Field Sales connector DB error, there can be an oversight or a problem with database compatibility. In addition to making that the connector is compatible with the version of your system, check the logs for detailed problem messages.

Hi Joshua,

 

We have the requirement to build map functionalities on web and mobile app it is like a (google map) for that we have implemented on web applications using  Field force connector it is working as we expected in web app and same things we configured on the mobile application wizard but we are not able to see the map in mobile as in web app. Please find the snap for the reference for map UI in web app, we are expecting the Open Street Map hyper link in mobile.
 

Web app Map Snap
 

Prem Kumar,

Hi!

This is not currently available in the mobile app.
You can inspect the Account address detail as an example of integration with OpenStreetMaps in the system and Field Force application as an example of maps functionality on mobile apps. 

And also, 

You can find information in these posts:

https://community.creatio.com/questions/account-address-map-mobile-application

https://community.creatio.com/questions/maps-mobile-application

 

Best regards,

Anton

Anton Starikov,

Hi Anton,

 

We have tried above mentioned approaches also but we couldn't get exact UI  as we expected  on mobile app.

We are expecting like a google map in mobile, it is used for delivering the Freight to the customer place. Please help us to achieve this functionalities in mobile.

Thanks,
Prem

Web app Map Snap

 

Show all comments
mobile
Mobile_Creatio
8.0

Hello, I recently started working with Creatio Mobile. I have downloaded the files and was able to create the Creatio APK through the SDKConsole utility. I have a question: how can I add a page within the application? I see that most of the app is based on WebView. My goal is to import a library from Pub.dev (in my case, call_log) and implement it to display the data on a page within this app.

If anyone could help me, I would be very grateful. Thank you.

Like 0

Like

1 comments

Hello,
In the mobile application there is an abillity to open custom JS pages using the handler logic, an example of such handler:

const openCustomPageRequest: OpenCustomWebViewPageRequest = {
   type: 'crt.OpenCustomWebViewPageRequest',
   $context: request.$context,
   controllerName: 'Terrasoft.controller.MobileSyncLogPage',
   viewXClass: 'Terrasoft.view.MobileSyncLogPage',
   parameters: {
       "customParam": 1
   }
};
HandlerChainService.instance.process(openCustomPageRequest);

controllerName - class name of JS controller 
viewXClass - class name of JS view 
parameters - additional parameters of custom page. To get the parameter call this method inside the controller this.getPageHistoryItem().getRawConfig().customParam

This handler should be added via the remote module (see this article) and using the @creatio/mobile-common library enabling the feature EnableMobileSDK in the Features page.

Show all comments