Child pages
  • Developing the Mobile Service Solution
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 8 Next »

The mobile service solution manages the syncronisation of the offline data.

Requirements:

  1. Needs a form with name "offline_data"
  2. The form offline_data needs a method ws_read(version,name)
  3. If the data shown in mobile app is user specific the form offline_data needs a method ws_authenticate(useruid,password)
  4. The mobile_service and rest_ws plugin to be installed

Constructing a offline data package for the mobile client

The ws_read(version,name) on the offline_data form has to return an OfflineDataDescription (=JSON) object filled with foundset data the developer wants the mobile client to retrieve.
An OfflineDataDescription instance is created with:

var retval = plugins.mobileservice.createOfflineDataDescription('data_');

Note: the argument is optional and is used to call rest endpoints for row data at forms starting with this prefix

Then we need to provide a list of relation names which should be used in traversal to find all data, like:

var traverse = new Array();
traverse.push('accountmanager_to_companies');
traverse.push('companies_to_contacts');

Lastly we have instruct the OfflineDataDescription to collect the data, starting with root foundset (containing records) and return.

retval.addFoundSet(fs_contact, traverse);
return retval;

Basically addFoundSet in the service solution exposes an unrelated foundset to the mobile client, which can be used in an unrelated way like in a (first) form or databaseManager.getFoundset(...)
For each record in the provided (unrelated) foundset the specified relations are traversed and all data taken.

User specific data

In order to provide a mobile client with user specific data the ws_authenticate(useruid,password) method should be added:

function ws_authenticate(useruid,password)
{
	//TODO find user and check password against pwhash column
	if (password == 'demo')//static demo check
	{
		var retval = new Object();
		retval.username = useruid;
		return retval;
	}
	return false;
}

In the ws_read method we can utilize the authenticate username variable via

var authenticate_info = questionParams.ws_authenticate[0];
globals.username = authenticate_info.username;

Here the authenticate username is put into a global variable which in turn can be used like:

//prepare personal data
var fs_contact = globals.contact_data$username;//global related foundset using username global var, containing the account manager contact

Full ws_read method for personalized data.

function ws_read(version,name)
{
	var questionParams = arguments[arguments.length-1];

	//create return value
	var retval = plugins.mobileservice.createOfflineDataDescription('data_');

	//setting the key for user_select relation
	var authenticate_info = questionParams.ws_authenticate[0];
	globals.username = authenticate_info.username;

	//prepare personal data
	var fs_contact = globals.contact_data$username;//global related foundset using username global var, containing the account manager contact

	/**
	 * @type {Array<String>}
	 */
	var traverse = new Array();
	traverse.push('accountmanager_to_companies');
	traverse.push('companies_to_contacts');

	retval.addFoundSet(fs_contact, traverse);
	return retval;
}

Providing/retrieving entity(=table) row data

Row/record data is retrieved in separate calls for each entity, for example for "orders" row data results in a call to "orders" form is made on ws_read method.
Note: If a prefix is provided in the offlinedata the call will endup at prefix+entityname, example for prefix "data_" the call happens on form "data_orders"

ws_read is with a list of pks it wants as row data for, example code:

function ws_read(version,method)
{
	var questionParams = arguments[arguments.length-1];

	if (method == 'list')
	{
		/**
		 * @type {String}
		 */
		var ids = questionParams.ids[0];
		if (ids != null && ids != '')
		{
			/**
			 * @type {Array<Object>}
			 */
			var idsa = ids.split(',', -1);
			if (idsa.length > 0)
			{
				foundset.loadAllRecords();
				var json = plugins.mobileservice.getRowDescriptions(foundset, idsa)
				return json;
			}
		}
	}

	throw 404;
}

TIP: since ws_read for entities is likely the same, it might be beneficial to create a base form containing this logic and extend from this form

ws_update is called for changes made by mobile client, example code:

function ws_update(data,version,pk)
{
	if (foundset.find())
	{
		foundset.contact_id = pk;
		var count = foundset.search();
		if (count > 0)
		{
			var rec = foundset.getRecord(1);
			rec.name_first = data.name_first;
			rec.name_last = data.name_last;
			rec.email = data.email;
			rec.phone_cell = data.phone_cell;
			databaseManager.saveData(rec);
		}
		foundset.loadAllRecords();
	}
}

ws_create is called for new records on the mobile client, example code:

function ws_create(data,version,pk)
{
	var rec = foundset.getRecord(foundset.newRecord());

	rec.name_first = data.name_first;
	rec.name_last = data.name_last;
	rec.email = data.email;
	rec.phone_cell = data.phone_cell;
	rec.company_id = data.company_id;
	databaseManager.saveData(rec);

	foundset.loadAllRecords();
}

Note: the retrieved PK (and derived FK's) is always UUID's if the underlaying datamodel is not UUID based, keep and apply a mapping!

Other pages
Unknown macro: {list-siblings}


  • No labels