Integrating to Sugar using a custom drawer action

There are so many possible approaches for integrating with Sugar that selecting the best one can be tricky.

When deciding to add new components into the Sugar user interface, the number of possibilities to consider is dizzying.Should I build a new component or override an existing one?Am I building a View, Layout, or custom Fields?Will a Dashlet give me enough screen real estate or will I need to create a new layout?

The goal of the Sugar Integration Building Blocks open source project is to provide sample code and most importantly the underlying design patterns that makes it easy to build best practice integrations.

Some integration use cases mean that a primary action has to be added to a Record or List view. For example, you may need to launch a wizard interface such one used with a Configure Price Quote (CPQ) solution on an Opportunity record.

A common CPQ flow would be to have a custom "Create Quote" action on an Opportunity record. This would launch an expansive Configurator wizard that, when complete, will need to push the new Quote, new Revenue Line Items, etc, back to the original Opportunity record.

The standard approach for this would be to add a button to the Record View or List View that launches a Drawer.

In order to make this design approach easier, we have added an HTML iframe drawer action as a new Building Block!  Now it is very easy to build a complete integration or proof of concept that utilizes a drawer!



Read more below to learn how it works.  It was designed in an upgrade safe way that does not interfere with any existing customizations that may exist on Record views or List views.

The Integration Flow

This building block contributes an action to the Opportunities Record layout but can be easily adapted to make a contribution to any other application screen (or Sidecar route).



Clicking the "Open Drawer" button will launch a configurable IframeDrawerLayout. This action uses our standard Drawer API.

app.drawer.open({

    layout: 'iframe-drawer',

    context: {

        model: model,

        url: "//httpbin.org/get?record="+model.get("id")+"&module=Opportunities",

        title: "IFrame Drawer"

    }

}, function(){

    // ... on close callback ...

});



Of course, for the example we just use the httpbin.org service to make it easy to show what the request looks like to a downstream web application. This context can give the downstream application what it needs to appropriately configure the interface appearing in the HTML iframe.  Passing the module name and the record ID would also allow this external application to push changes back into the original Opportunity record in Sugar via the REST API.

Open drawers are placed on to the foreground, which means that when the drawer is closed by hitting the "Cancel" button that the control returns to the Opportunity record. You can still see the Opportunity at the bottom of the screenshot above. You can also close the drawer programmatically by calling the following function.

app.drawer.close();

Adding the button and event handling code

It is very common for Sugar instances to have significant customizations on Record or List view controllers. So for this approach, we want to maximize our compatibility since we may not always know when such customizations exist ahead of time in a particular Sugar instance. So we have intentionally avoided overriding a Sidecar controller in this implementation.

Adding a button that triggers a Sidecar event can be accomplished entirely using a Sidecar metadata extension, such as the one below.

<?php

/**

* Copyright 2016 SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license.

*/

//Insert our custom button definition into existing Record View Buttons array for Opportunities module

array_unshift($viewdefs['Opportunities']['base']['view']['record']['buttons'],

    array(

        'name' => 'custom_button',

        'type' => 'button',

        'label' => 'Open Drawer',

        'css_class' => 'btn-primary',

        //Set target object for Sidecar Event.

        //By default, button events are triggered on current Context but can optionally set target to 'view' or 'layout'

        //'target' => 'context'

        'events' => array(

            // custom Sidecar Event to trigger on click.  Event name can be anything you want.

            'click' => 'button:open_drawer:click',

        )

    )

);

We then add the following JavaScript code into the Sugar page using a JSGroupings extension.

(function(app){

    /**

     * Copyright 2016 SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license.

     */

    //Run callback when Sidecar metadata is fully initialized

    app.events.on('app:sync:complete', function(){

        var openDrawerCallback = function(model){...};

        //When a record layout is loaded...

        app.router.on('route:record', function(module){

            //AND the module is Opportunities...

            if(module === 'Opportunities') {

                //AND the 'button:open_drawer:click' event occurs on the current Context

                app.controller.context.once('button:open_drawer:click', openDrawerCallback);

            }

        });

    });

})(SUGAR.App);

Our custom JavaScript waits until login and metadata sync is complete and then attaches a listener to Sidecar's Router.  This listener is used to determine when the desired layout is being displayed and add a listener to the current Context object for our button's click event.

Get the entire example in Github!

The full example is available in Github as a complete package!  For more information on how to work with these Module Loadable packages in this repository, check out the Packages README.
Parents Comment Children
No Data