Skip navigation
All Places > Developer > Blog > 2015 > June
2015

Post originally written by tshubbard.

 

For Sugar Developers, the Dashboard and Dashlet framework provided in Sugar 7 really helps you to build slick reusable Dashlets that can be targeted for certain parts of the app or made globally available anywhere in the app.  They're also really easy to use which is something we are gonna highlight today.

 

For a more detailed look at how Sugar 7 Dashlets work then you should read up on the topic in the Sugar Developer Guide.  The focus on this post is to highlight the most basic elements necessary that we can then build upon in later posts.

 

A quick reminder

 

Just some quick advice to anyone about to embark on the Dashlet development journey.  We recently featured a post on a common Sugar 7.x dashlet gotcha.  Basically, dashlet metadata gets copied into database when you add a dashlet to a dashboard.  You'll need to delete the dashlet or the dashboard and add it all over again whenever you modify dashlet metadata.  We are working on making this seamless in future but this is something you should remain aware of when building dashlets.

 

Creating a Dashlet Summarized

 

Dashlets are simply Sugar 7 Views that have some extra features added via the 'Dashlet' plug-in and an additional metadata requirement. This tutorial will be brief because creating a basic dashlet is incredibly easy.  As with any Sugar 7 view, we will need three files: a JS controller, a PHP metadata file, and a Handlebars template for the presentation.

 

Shall we begin?

 

Step 1: Create a 'hello-world' directory

 

In your Sugar 7 instance, create a new directory called custom/clients/base/views/hello-world and create three files called hello-word.js, hello-world.php, and hello-world.hbs inside.  This is just like any other Sidecar view in Sugar 7.

Sugar 7 Dashlets are just like any other Sidecar view


 

Step 2: Implement the Dashlet Controller (JavaScript)

 

To make this "hello-world" view a dashlet, all we need to do is add one line to the view's JS Controller.  This adds the 'Dashlet' Sugar 7 plug-in to your view.  This applies a bunch of changes in behavior to your view that gives it a Dashlet nature.  Plug-ins are essentially Sugar 7's implementation of the Mixin JavaScript design pattern.  You can examine the Dashlet plug-in implementation under include/javascript/sugar7/plugins/Dashlet.js if you are curious but for the most part you don't need to worry about the details.  Just know that all dashlets needs to include the 'Dashlet' plug-in in their controller.

At a minimum, Dashlet controllers must include the 'Dashlet' plug-in.
hello-world.js

 

hello-world.js

({
    plugins: ['Dashlet']
})

 

Step 3: Implement the Dashlet Metadata (PHP)

 

Dashlet metadata is also fairly straightforward. Make sure your metadata is wrapped in an array labeled 'dashlets' and it should have the following params:

  • label - A String label, preferably a language string key "LBL_HELLO_WORLD_TITLE" or something similar that you've included in a custom language file
  • description - A String description, again, preferably a language string key
  • config - an array of config params (if applicable) that allows users to configure the dashlet before it's added to a dashboard
  • preview - an array of preview params (if applicable) to be passed when your dashlet is "previewed" when being added to a dashboard
  • filter - an array of filter params (if applicable) for making this dashlet only show up on a specific view or module
At a minimum, all Dashlet metadata must include a 'dashlets' array that defines a 'label' and 'description'.
hello-world.php

 

hello-world.php

<?php

$viewdefs['base']['view']['hello-world'] = array(
'dashlets' => array(
array(
'label' => 'Hello World!',
'description' => 'Hello World is a basic dashlet for the SugarCRM Cookbook tutorial.',
'config' => array(
            ),
'preview' => array(
            ),
'filter' => array(
            )
        ),
    ),
);

 

Step 4: Implement the Dashlet Template (Handlebars)

 

The template can be as basic as you want it to be.  There is no requirement for the content you put into the template.

There is no minimum requirement for Dashlet templates.  You are in full control of the presentation.
hello-world.hbs

 

hello-world.hbs

<p>
    Hello World!
</p>

 

Step 5: Run Quick Repair and Rebuild

 

So that is all the programming we need to do. With those three files in place, we just need to rebuild the cache so that Sugar 7 picks up our new Dashlet and makes it available to end users.

 

The simplest way to do this is to run Quick Repair and Rebuild or by manually removing the contents of your cache/ directory and reloading the Sugar 7 web app which will then rebuild the file cache automatically.

 

Step 6:  Add your Dashlet to a Dashboard

 

If you login now as any user and try to add a dashlet to any dashboard, you should see your "Hello World" dashlet listed.  This dashlet is an option within all dashboards because we did not specify and dashlet filter criteria in Step 3 when we defined the metadata.

 



 

After adding it to a dashboard and saving it, you should see your dashlet appear just like the one below.

 



If you were at UnCon in April 2015 then you know that one of our hottest topics was plans for a SugarCRM Mobile SDK.  Since mobile devices and mobile use cases are such a key part of what Customer Relationship Management and Customer Experience is today and will be in the future, we are planning to enhance the SugarCRM Mobile development platform available to Sugar Developers.  You can follow the blog here for updates on that as they become available in the future.

 

However, there are already many different ways that developers can customize the behavior of the existing SugarCRM Mobile application today.  That will be the focus of today's post.  In fact, you can drastically customize the behavior of the SugarCRM Mobile application without the hassle of having to distribute any custom code or apps to end-user Mobile devices.  All these techniques listed below involve only Sugar 7 server side code and metadata customizations.

 

Metadata based Customizations

 

As every Sugar Developer should be well aware, Sugar metadata serves as the architectural backbone of the Sugar 7 platform.  All Sugar 7 clients, including the SugarCRM Mobile application, are driven via Sugar metadata which means changes in Sugar metadata can already be used to reflect changes in appearance and behavior of the Mobile client without having to write a line of JavaScript.

 

Mobile Layouts & Sugar Logic

Sugar Logic allows you to utilize expressions and actions to establish dependencies between fields within a Sugar module.  It is already a best practice to utilize Sugar Logic where possible since it is applied consistently across the application both client and server-side.  So always remember that Sugar Logic works in SugarCRM Mobile too.

 

For example, if you want to display custom information or messages to a user on Mobile, you could add a read-only dependent field to Mobile Layouts to deliver it.

 

Try this example, all you need to do is create a calculated field in Sugar Studio and configure the formula as seen below.

 

sugarfield_next_step_c.php

<?php
// created: 2015-06-05 10:27:18
$dictionary['Lead']['fields']['next_step_c']['duplicate_merge_dom_value']=0;
$dictionary['Lead']['fields']['next_step_c']['labelValue']='Next Step';
$dictionary['Lead']['fields']['next_step_c']['full_text_search']=array (
'boost' => '0',
'enabled' => false,
);
$dictionary['Lead']['fields']['next_step_c']['calculated']='1';
$dictionary['Lead']['fields']['next_step_c']['formula']='ifElse(equal(count($tasks),0),"You must create a follow up Task for this Lead!",concat("Complete ",toString(related($tasks,"name"))))';
$dictionary['Lead']['fields']['next_step_c']['enforced']='1';
$dictionary['Lead']['fields']['next_step_c']['dependency']='';

 



 

API based Customizations

 

Similar to Sugar metadata, the Sugar 7 REST API serves as the transport backbone for the Sugar 7 platform.  All Sugar 7 clients, including the SugarCRM Mobile application, utilize the same APIs to communicate with Sugar server.  This makes the APIs the ideal critical point to intercept messages that come from the Mobile client.

 

API Logic Hooks

 

Most Sugar Developers are familiar with the Module Logic Hooks that are available in the system.  For example, whenever a record gets saved to the server in Sugar the before_save and after_save logic hooks are triggered.  It doesn't matter that these requests originated from the Mobile client, the base Sugar 7 web client, the Sugar portal client, or some other web services integration.

 

However, each user session (and therefore each API request) does have a platform identifier associated with it.  This is gets associated with the session when the user logged in.  For requests coming from the SugarCRM Mobile application, this platform identifier is always "mobile".  With this in mind, it's possible to intercept each API call from a Mobile client session via one or more API Logic Hooks in order to do something special in those cases.  In the example below, we just write information about the request to the sugarcrm.log file.

 

To try this example, copy the following two files to custom/MobileApiLogicHook.php and  custom/Extension/application/Ext/LogicHooks/after_routing_mobile.php.

 

after_routing_mobile.php

<?php

$hook_version = 1;
$hook_array = Array();

$hook_array['after_routing'] = Array();
$hook_array['after_routing'][] = Array(
//Processing index. For sorting the array.
1,

//Label. A string value to identify the hook.
'after_routing mobile logic hook',

//The PHP file where your class is located.
'custom/MobileApiLogicHook.php',

//The class the method is in.
'MobileApiLogicHook',

//The method to call.
'logMobileAfterRouting'
);

MobileApiLogicHook.php
<?php

if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

/**
* Example Mobile API Logic Hooks class
**/
class MobileApiLogicHook
{
/**
     * Logic hook function tied to 'after_routing' event
*/
function logMobileAfterRouting($event, $arguments)
    {
//Sugar Logger
global $log;
//If request came from a Mobile platform
if($arguments['api']->platform == "mobile"){
$path = $arguments['api']->getRequest()->getPath();
//Write request path to sugarcrm.log file
$log->fatal("Mobile request to " . json_encode($path));
        }

    }
}

Thu Jun 11 13:23:52 2015 [15726][-none-][FATAL] Mobile request to ["oauth2","token"]

 

Thu Jun 11 13:23:53 2015 [15726][1][FATAL] Mobile request to ["me"]

 

Thu Jun 11 13:23:53 2015 [15635][1][FATAL] Mobile request to ["metadata"]

 

Thu Jun 11 13:23:56 2015 [15635][1][FATAL] Mobile request to ["ping","whattimeisit"]

 

Thu Jun 11 13:23:56 2015 [15635][1][FATAL] Mobile request to ["ping"]

 

Thu Jun 11 13:23:57 2015 [15726][1][FATAL] Mobile request to ["Dashboards"]

 

Thu Jun 11 13:23:57 2015 [15635][1][FATAL] Mobile request to ["Users","filter","count"]

 

Thu Jun 11 13:23:57 2015 [15726][1][FATAL] Mobile request to ["bulk"]

 

Thu Jun 11 13:23:57 2015 [15726][1][FATAL] Mobile request to ["Dashboards","f3b37ac6-60f2-0606-18a0-55773d752273"]

 

Thu Jun 11 13:23:57 2015 [15726][1][FATAL] Mobile request to ["Dashboards","be9896e2-cddc-f88c-c161-55773d8013ed"]

 

...

 

Override API endpoints for Mobile platform

 

Or you can define a custom API endpoints for the Mobile platform to handle specific requests entirely differently for the Mobile clients than you would for other clients.  In the example below, we have modified the OAuth 2 API that is used for authentication to restrict mobile device access to Sugar 7.  This restriction could be based upon the role of the current user, whether Sugar 7 is being accessed via the native iOS, Android app or a mobile device's web browser.  It is even possible to check the kind of device being used (tablet, phone, or PC).

 

To try this example, add the following file to custom/clients/mobile/api/RestrictedOAuth2MobileApi.php

 

RestrictedOAuth2MobileApi.php

<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

require_once 'clients/mobile/api/OAuth2MobileApi.php';

/**
* Example of how to override the core OAuth2MobileApi class in order to alter SugarCRM Mobile authentication behavior
**/
class RestrictedOAuth2MobileApi extends OAuth2MobileApi {

/**
     *
     * By overriding the token function, we can show an example of how to restrict user access to Sugar 7 via Mobile clients/devices.
     *
     * @param ServiceBase $api The service api
     * @param array $args The arguments passed in to the function
     * @throws SugarApiExceptionNotAuthorized If user is not allowed or not using a supported mobile client
     * @return array Access token if login successful
*/
public function token(ServiceBase $api, array $args)
    {
global $current_user;

/** 
        *   $args['client_info'] contains information about the client being used
        *
        * For example,
        *       ['client_info']['app'] is an array of information about the SugarCRM Mobile app itself (app name, app version, if it's native or not, etc.)
        *       ['client_info']['browser'] is an array of information about the web browser being used (web kit enabled, user agent string, etc.)
        *       ['client_info']['device'] is an array of booleans ('desktop', 'phone', and 'tablet') for the type of device being used
        *     
        **/

// No tablets!  (for some reason.)
if($args['client_info']['device']['tablet']){
throw new SugarApiExceptionNotAuthorized();
        }

// continue to perform login as we normally would, we need to do this in order to collect $current_user id
$authData = parent::token($api, $args);

// This is a valid user, but we then need to check if they are on a Restricted role
$roles = ACLRole::getUserRoleNames($current_user->id);
// If user is in a Restricted role...
if (in_array('Restricted', $roles)) {
//Log user back out to cleanup session
parent::logout($api, $args);
//And throw Not Authorized exception.
throw new SugarApiExceptionNotAuthorized();
        }
return $authData;
    }


}

 



 

Metadata & API based Customizations

 

You can also combine the techniques described above to create more sophisticated SugarCRM Mobile customizations.

 

Lightweight Custom Modules

 

While SugarCRM Mobile does not yet support custom views, it does support the addition of new custom modules.  So if you already have an existing Custom Module that you want to display in the Mobile client then consider creating an additional simplified Custom Module that is a facade for your existing custom module or even one of Sugar 7's BWC modules.  You can then use a Sugar Job to synchronize key data into your mobile Custom Module.   Or (as seen below) you can modify the Mobile Module's API endpoints to pull data from other Modules or sources in real time.

 

To try this example, you will need to create a test_MobileContracts custom module using Module Builder, define the layouts, fields, metadata, etc, for it and then enable it for Mobile via the Admin panel.  Then add the following file to modules/test_MobileContracts/clients/mobile/api/MobileContractsMobileFilterApi.php

 

MobileContractsMobileFilterApi.php

<?php

require_once 'clients/base/api/FilterApi.php';

/**
* Class MobileContractsMobileFilterApi
*
* Tested with Sugar 7.6
*
* Example of how to build a simple proxy API that can be used to make API requests to one module pull data from another module.
* In this case, we can pull data from the Contracts module (which is not implemented in SugarCRM Mobile yet) via a
* proxy Custom Module called test_MobileContracts.  This is a way to satisfy a need for a limited view of Contracts
* data from within the SugarCRM Mobile app.
*
*/
class MobileContractsMobileFilterApi extends FilterApi
{
public function registerApiRest()
    {
//New API definition that the base Filter API endpoint for only test_MobileContracts module
return array(
'filterModuleAll' => array(
'reqType' => 'GET',
'path' => array('test_MobileContracts'),
// Not needed because we will hard code module argument below.
// 'pathVars' => array('module'),
'method' => 'myFilterList',
'jsonParams' => array('filter'),
'shortHelp' => 'Proxy API for retrieving all Contract records.',
'exceptions' => array(
// Thrown in filterList
'SugarApiExceptionInvalidParameter',
// Thrown in filterListSetup and parseArguments
'SugarApiExceptionNotAuthorized',
                ),
            ),
        );
    }

public function myFilterList(ServiceBase $api, array $args, $acl = 'list')
    {
//Hard code module redirect
$args['module'] = 'Contracts';

// We could transform the 'fields' argument here, but we could also assume that
// the field names being passed match those found in Contracts module

//Call normal filter API endpoint with our modified arguments
return $this->filterList($api, $args, $acl);
    }

}

 



In last week's post on the Font Awesome 4.x upgrade in Sugar 7.6 we mentioned that Sugar Engineering has been putting together a compatibility package.  This package can be installed into Sugar 7.6 instances to add Font Awesome 3.2.1 back.

 

That package is now ready.  It can be installed into Sugar 7.6 Beta or Sugar 7.6 GA once that is available.

 

Package Installation

 

This package installs the Font Awesome 3.2.1 library used in Sugar 7.5 into a Sugar 7.6 instance. This restores the function of old Font Awesome CSS classes if there is code in a Sugar 7.6 instance that still relies on Font Awesome 3.2.1 in order to display icons.

 

SugarCRM offers no support on the use of this package.  We need Sugar Developers to move to Font Awesome 4.x.Step 1: Identify that you actually need this package.  If you find that icons are missing from customizations in a Sugar 7.6 instance then installing this package will restore them.  Specifically, if your custom Sugar 7 HTML contains CSS classes that start with "icon-".Step 2: Download the FontAwesome-321 package.Step 3: Install it on your Sugar 7.6 instance using Module Loader.

 

Your icons will then reappear.

 

Performance Warning

 

Installing this package does cause a degradation in render performance in Sugar 7.6. Sugar 7 is moving from 3.2.1 to 4.x for the improved performance. Only use this package if you know it is necessary.  Once in use, it should be uninstalled as soon as code customizations are migrated.

 

Moving to Font Awesome 4.x is easy, check out this blog post for migration details.If you have any questions, please e-mail developers@sugarcrm.com.