Friday 24 October 2014

Google map integration with Open UI – route planning based on sales reps calendar!

Hi All,

I would love to update more often on my blog but unfortunately, my work load is pulling me back. While I was hiding from my blogging, was busy improvising our sales reps day to day operations by means of integrating their visits with Google optimized route planning.

Before you can understand the subsequent content of my blog, you need to understand the google map API itself. I am not going to go into that but provide you the link to explore your self.  So, click on the image below and explore the Google map API.
image

Ok demo first. Please watch below video for an insight as to what I will be talking next.






The business scenario goes like this. As soon as your sales rep logs onto Open UI, he will be shown with his current appointments in the calendar applet and the corresponding locations are plotted on the map along with full direction details at the bottom of the screen.

How to go about it? (High level)




1) You need to build a new view (I copied home page view where it already had the Calendar Applet). I added Activity List Applet and the calendar Applet to it. (70% –30% ratio).

2) Your list applet will change its content based on the visits listed on your calendar applet. I mean, if you change the day on your calendar, you will see the appointments on that day on both the calendar applet and the list applet as they are based on same BC.

3) Now add a custom PR for your list applet to replace it’s list contents and display a Google map instead! Sounds tricky? continue reading then.

1st mystery to resolve is to how to access Google Map APIs. As you know jquery or any other 3rd party plugins where they provide you with a local copy of .js files which you can very easily include into your PR. But Google doesn’t do that – they provide you a URL to include. The main reason is Google free service is limited ( you can have limited number of direction requests, geocoding etc). You can get a paid key if your usage is higher. Open UI out of the box, doesn’t provide options to include URL based js to your PM/PR. So, after looking around a while, I found this vanilla js – jqmmapctrl.js (under /scripts/siebel). You need to include Google API via ajax calls.

Here is the outline as to how to include Google map API using ajax.
    var googleAPILoaded = false; // variable to tell you whether the google API load was success or not
//This function will use jquery getScript to include google api. Once the API is loaded it will callback your function: loadAPIs
   
var preGoogleLoadAPI = function(){
        googleAPILoaded = false;
        var prevValue = $.ajaxSetup().async;
        $.ajaxSetup({
            async: false
        });
        $.getScript("https://www.google.com/jsapi?callback=loadGAPIs", function() {});
        $.ajaxSetup({
            async: prevValue
       
});
    }

//Here you will set your global variable to true to indicate that APIs are loaded
   
var loadGAPIs = function () {
        SiebelJS.Log("[LoadGAPIs] Google APIs Loaded...");
        googleAPILoaded = true;
    }; 

//This function will take a function name in which you have defined all your mapping logic and will call it through google.load api
    var LoadAPI = function (func, retryCount) {
        if (!googleAPILoaded || typeof (google) == "undefined") {
            if (retryCount < 10) {
                retryCount++;
                setTimeout(LoadAPI(func, retryCount), 1000);
            }
        }
        else {
            google.load("maps", "3", { other_params: 'libraries=places,geometry&sensor=false', callback: func });
            console.log("google load called");
        }
    };


That’t it! Above is basically your framework for any google integration. So next steps to gather data from your calendar and call google API and details below.

step 1) Beatify your list applet by replacing it with two DIVs. One for the map and one for direction. On your PR - ShowUI function (gets called only once initially when screen is loaded) below is what I did.
> Get the handle for your applet placeholder from your pm. 
                var pm = this.GetPM();
                var placeHolder = pm.Get("GetPlaceholder");
> Build a string containing HTML that you want to replace with. In my case, a map_container div to hold both map_canvas an directions_panel divs.

                var strHTML = '<div class="map_container" id="map_container" style="z-index: 1; border: 0" src="">';
                strHTML += '    <div id="map_canvas" style="padding:2px; float:center;width:98%;max-width:99%;height:77.5%%; overflow:hidden;border: 2px solid;border-radius: 5px;"></div>';
                strHTML += '    <div id="directions_panel" style="background-color:#C8CBDA;padding:2px;float:center;height:19.5%;width:98%;max-width:99%;text-align:left;overflow:auto;border: 2px solid;border-radius: 5px;"></div>';
                strHTML += '</div>'; 
> Replace the list applet layout with your HTML 
                $("#" + placeHolder).append(strHTML);
> Adjust the height and width of your main map_containder div so that it fits nicely.
                $(".map_container").width($(".map_container").parent().parent().parent().width() - 4);
                $(".map_container").height($(window).height() / 1.45);

Step 2) in ShowUI after above steps, Call your function preGoogleLoadAPI to load google api
preGoogleLoadAPI();

step 3) Write your function to display the directions on your map. Here is where your google API knowledge comes handy. You might find it hard to understand below code – see if you can make out.
InitMap = function () {//remove any existing markers previously drawn
                    RemoveMarkers();
//update your direction panel with a message!
                    var summaryPanel = $("#directions_panel");
                    summaryPanel.html("Waiting for way points!"); 

//get handle for geo coder, directionService and directionDisplay
                    geocoder = new google.maps.Geocoder();
 
                    directionsService = new google.maps.DirectionsService();
                    directionsDisplay = new google.maps.DirectionsRenderer();
//default client position
                    var clientPosition = new google.maps.LatLng(41.850033, -87.6500523);
 
                    var mapOptions = {
                        zoom: 15,
                        mapTypeId: google.maps.MapTypeId.ROADMAP,
                        center: clientPosition
                    };
 
                    var contentString = '<div id="content" style="width:100px; height:20px">' +
                      '<div id="bodyContent">' +
                      '<p>Your Location!</p>' +
                      '</div>' +
                      '</div>';
//to get current GPS position of the user
                    if (navigator.geolocation) {
                        navigator.geolocation.getCurrentPosition(function (position) {
                            clientPosition = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
                            mapOptions.center = clientPosition;
                            map = new google.maps.Map($("#map_canvas")[0], mapOptions);
 
                            //'../images/ebus.gif'"https://static.rewardgateway.co.uk/img/mapicons/home-icon2.png"
                            AddMarker(clientPosition, contentString, '../images/custom/home2.png');
                            directionsDisplay.setMap(map);
//PrepDirectionInputs - This is where you will read your calendar info and plot routing!
                            PrepDirectionInputs(pm);
                        }, function () {
                            mapOptions.center = clientPosition;
                            map = new google.maps.Map($("#map_canvas")[0], mapOptions);
                            AddMarker(clientPosition, contentString, '../images/custom/home2.png');
 
                            directionsDisplay.setMap(map);
 
                            PrepDirectionInputs(pm);
 
                        }, { timeout: 5000 });
                    }
                    else {//GPS is disabled on user’s device!
                        mapOptions.center = clientPosition;
                        map = new google.maps.Map($("#map_canvas")[0], mapOptions);
                        AddMarker(clientPosition, contentString, '../images/custom/home2.png');
 
                        directionsDisplay.setMap(map);
 
                        PrepDirectionInputs(pm);
 
                    }
                };

Step 4) Call, InitMap using google.load defined in function LoadAPI above. I had to come up with below to ensure that google APIs are loaded before I call them!

var check_mapAPILoaded = function () {
                    if (!googleAPILoaded)
                        setTimeout(check_mapAPILoaded, 500);
                    else {
                        LoadAPI("InitMap", 0);
                    }
                } 
                //call it
                check_mapAPILoaded();

That’s it! Define the rest of the supporting functions and you are almost there!
The main one is PrepDirectionInputs function. Below is what I am doing in it.

> Loop through the RecordSet of the list applet. For each record found,
> capture Longitude and Latitude stored against the primary address of the visit account.Add it to google api request variable
> For Google map direction services (example here: waypoints and google map api), you need to define Start, End and WayPoints. So, your first appointment will be start and the last will be End and the middle ones will be waypoints. Google API will plot an optimal route from start to end covering all the waypoints.
> Call Google API, direction service to plot on the map_canvas! 
directionsService.route(…)
I am going to stop my explanations here otherwise, my blog will be 1000s of lines!

One thing to remember, your addresses should have Latitude and Longitude populated for accurate direction rendering. You could use geocoding but will be fiddly to manage.

Here is the final PR file for your ref: GoogleMapApiPR.js

Next blog coming shortly is on plotting all the customers based on importance or last visited near to your current location. Till then, stay tuned!

Cheers,
Shiv

1 comment:

  1. Google Map Service Provider

    Want to get Google Map Service Provider in Ahmedabad? Then Mart2Global is the complete best solution Company. Mart2global is a premier SEO, SMO, Social Media and Paid Ads Marketing Company in Ahmedabad, India, which provides complete Digital Marketing solution.

    ReplyDelete