Monday, April 7, 2014


With the rise of the Web and the HTML5, libraries like Angular , Knockout, Backbone started becoming popular. Among them somehow Angular stood out of the queue and looked more promising than others. It was also because of the fact that it is maintained by Google!

With VF pages I somehow couldn't find a good way to implement Angular, I have been tinkering with the library to make it work with Visualforce. I somehow wanted to marry Angular Factories with Visualforce Remoting and ended up doing the same using promise.


Here is small example how to use Visualforce Remoting with Angular.

Visualforce Page


<apex:page controller="AngularRemoting_Con">  
   <vs:importvisualstrap />  
   <vs:visualstrapblock >  
   <apex:includeScript value="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.min.js"/>  
   <!--Remoting Stuff-->  
   <script>  
     function getSobjects(callback){              
       Visualforce.remoting.Manager.invokeAction(  
         '{!$RemoteAction.AngularRemoting_Con.getData}',  
         callback,  
         {escape: false}  
       );        
     }  
   </script>  
   <script>  
     var vfremote = angular.module('VFRemoting',[]);  
     vfremote.factory('VFRemotingFactory',function($q,$rootScope){  
       var factory = {};  
       factory.getData = function(){  
         var deferred = $q.defer();  
         getSobjects(function(result){  
           $rootScope.$apply(function(){  
             deferred.resolve(result);  
           });  
         });  
         return deferred.promise;  
       }  
       return factory;  
     });  
     vfremote.controller('VFRemoteController',function($scope,VFRemotingFactory){  
       VFRemotingFactory.getData().then(function(result){  
         $scope.data = result;  
       });  
     });  
   </script>  
   <div ng-app="VFRemoting">  
     <div ng-controller="VFRemoteController">  
       <ul class="list-group">  
         <li ng-repeat="acc in data" class="list-group-item">{{acc.Name}}</li>  
       </ul>  
     </div>  
   </div>  
   </vs:visualstrapblock>  
 </apex:page>


Controller Class


 public class AngularRemoting_Con {  
   @RemoteAction  
   public static List<SObject> getData(){  
     return [SELECT Id,Name FROM Account];  
   }  
 }  


How it looks like ?


A bit more about the pages

  • The pages uses VisualStrap for styling, that can be removed along with all the components starting with namespace "vs".
  • The Angularjs brings data from controller using Visualforce Remoting, it depends on "getSobjects" method to call controller method.
  • AngularJs uses Factories to communicate with remoting method "getSobject"

This page can be extended to do a lot more things, bringing data dynamically to the VF pages, with the two way binding that angular provides, you can use this to make superfast single page apps.

I am looking forward to Visualforce Remote objects and probably will be posting a blog about how to use them with AngularJS, but at the end I don't think there would be much of differences rather than some basic changes in the code structure. And obviously with Remote objects you won't need a controller!


Thursday, March 13, 2014


Salesforce has recently unveiled the new Salesforce1 app that lets you create mobile app very easily using technologies like JS, Visualforce and HTML and yes of course you can use VisualStrap create mobile ready pages.

Since Visualstrap is based on Bootstrap it inherits all the features from Bootstrap. Its a very powerful, sleek, front-end framework that lets you create mobile ready pages very fast!

Creating a Visualforce Page "VSDashboardS1"


So lets start with a User Dashboard / Overview page that we talked earlier here http://blogforce9.blogspot.in/2014/01/visualstrap-possibilities.html

Desktop View

Prerequisite 

Few things that needs to be considered


  • Desktop & Mobile support : Since we are going to support the page both on desktop and mobile we need to find a way to stack the grids on mobile devices so that they can be easily viewed. This can be easily done by using proper grid classes.
  • Navigation : We have to make sure all the links are updated, so that every thing works with Salesforce1 and Desktop
  • Responsive : The page needs to be responsive so that it fits in the screen of different mobile devices.


Desktop & Mobile support 

To make sure the grids properly stack up according to devices we should have to select proper column/ grid classes. In this example we are going to have three blocks per row, since a row in Bootstrap is of 12, each block should span to 4 units, hence the type "col-md-4"

<vs:row>  
   <vs:column type="col-md-4">  
           ...  
   </vs:column>  
   <vs:column type="col-md-4">  
           ...  
   </vs:column>  
   <vs:column type="col-md-4">  
           ...  
   </vs:column>  
 </vs:row>    

col-md-* classes are displayed in single row in a device with regular display where as they get stacked in mobile devices with smaller displays.


Navigation


We have to make sure navigation works for both Salesforce1 and  desktop, this can be done by detecting whether the app is viewed in Salesforce1 or Desktop. Have a look at the below JS function , the function checks whether "sforce.one" exists (which exists for Salesforce1) and switches the navigation method accordingly.

function goToDetailPage(recId){  
       if(typeof sforce != 'undefined' && typeof sforce.one != 'undefined'){  
         sforce.one.navigateToSObject(recId);  
       }  
       else{  
         window.location.href = '/'+recId;  
       }  
       return false;  
     }  


Responsive

Visualstrap grid classes are all responsive and hence they will adapt according to screen width.


The Design

To make sure the page uses all the real estate available on the screen, the page should be stacked vertically for mobile where as it should span horizontally for desktop. This is generally done use grid classes. 

Desktop layout
Mobile Layout


VF Page


 <apex:page sidebar="false" docType="html-5.0" controller="VSDashBoard_Con">  
   <vs:importvisualstrap />  
   <script>  
     function goToDetailPage(recId){  
       if(typeof sforce != 'undefined' && typeof sforce.one != 'undefined'){  
         sforce.one.navigateToSObject(recId);  
       }  
       else{  
         window.location.href = '/'+recId;  
       }  
       return false;  
     }  
   </script>  
   <vs:visualstrapblock style="padding:5px" >  
     <center>   
       <vs:pageheader title="User Dashboard" icon="calendar" subtitle="{!$User.FirstName} {!$User.LastName}"/>   
     </center>  
     <vs:row >  
       <vs:column type="col-md-4">  
         <vs:panel title="Tasks" type="primary">  
           <vs:well style="text-align:center;">  
              <vs:glyph icon="tasks" style="font-size:40px"/> &nbsp;<span style="font-size:54px">{!Tasks.size}</span>  
              <p class="text-muted">Tasks due for Today</p>  
           </vs:well>  
           <apex:dataTable value="{!Tasks}" var="task" styleClass="table table-condensed table-hover table-bordered" rows="3">  
             <apex:column headerValue="Subject">  
               <apex:outputLink onclick="goToDetailPage('{!task.Id}')">{!task.Subject}</apex:outputLink>  
             </apex:column>  
             <apex:column value="{!task.Status}" headerValue="Status"/>  
             <apex:column value="{!task.ActivityDate}" headerValue="Due Date"/>  
           </apex:dataTable>  
           <vs:alert rendered="{!Tasks.empty}" type="success" style="text-align:center">  
             <vs:glyph icon="ok-sign"/> No records to display  
           </vs:alert>  
         </vs:panel>  
       </vs:column>  
       <vs:column type="col-md-4">  
         <vs:panel title="Cases" type="primary">  
           <vs:well style="text-align:center;">  
              <vs:glyph icon="briefcase" style="font-size:40px"/>&nbsp;<span style="font-size:54px">{!Cases.size}</span>  
              <p class="text-muted">Assigned Cases</p>  
           </vs:well>  
           <apex:dataTable value="{!Cases}" var="case" styleClass="table table-condensed table-hover table-bordered" rows="3">  
             <apex:column headerValue="Case Number">  
               <apex:outputLink onclick="return goToDetailPage('{!case.Id}')" >{!case.CaseNumber}</apex:outputLink>  
             </apex:column>  
             <apex:column value="{!case.Status}" headerValue="Status"/>  
             <apex:column value="{!case.Priority}" headerValue="Priority"/>  
           </apex:dataTable>  
           <vs:alert rendered="{!Cases.empty}" type="warning" style="text-align:center">  
             <vs:glyph icon="exclamation-sign"/> No records to display  
           </vs:alert>  
         </vs:panel>  
       </vs:column>  
       <vs:column type="col-md-4">  
         <vs:panel title="Leads" type="primary">  
           <vs:well style="text-align:center;">  
              <vs:glyph icon="user" style="font-size:40px"/>&nbsp;<span style="font-size:54px">{!Leads.size}</span>  
              <p class="text-muted">Unread Leads</p>  
           </vs:well>  
           <apex:dataTable value="{!Leads}" var="lead" styleClass="table table-condensed table-hover table-bordered" rows="3">  
             <apex:column headerValue="Name">  
               <apex:outputLink onclick="return goToDetailPage('{!lead.Id}')" >{!lead.Name}</apex:outputLink>  
             </apex:column>  
             <apex:column value="{!lead.Status}" headerValue="Status"/>  
             <apex:column value="{!lead.CreatedDate}" headerValue="Created Date"/>  
           </apex:dataTable>  
           <vs:alert rendered="{!Leads.empty}" type="warning" style="text-align:center">  
             <vs:glyph icon="exclamation-sign"/> No records to display  
           </vs:alert>  
         </vs:panel>  
       </vs:column>        
     </vs:row>  
     <vs:row >  
       <vs:column type="col-md-6">  
         <vs:panel title="Last Viewed Accounts" type="primary">  
           <apex:dataTable value="{!Accounts}" var="acc" styleClass="table table-condensed table-hover table-bordered" >  
             <apex:column headerValue="Name">  
               <apex:outputLink onclick="return goToDetailPage('{!acc.Id}')" >{!acc.Name}</apex:outputLink>  
             </apex:column>  
             <apex:column value="{!acc.Type}" headerValue="Type"/>  
             <apex:column value="{!acc.BillingState}" headerValue="State"/>  
           </apex:dataTable>  
           <vs:alert rendered="{!Accounts.empty}" type="warning" style="text-align:center">  
             <vs:glyph icon="exclamation-sign"/> No records to display  
           </vs:alert>  
         </vs:panel>  
       </vs:column>  
       <vs:column type="col-md-6">  
         <vs:panel title="Last Viewed Contacts" type="primary">  
           <apex:dataTable value="{!Contacts}" var="contact" styleClass="table table-condensed table-hover table-bordered" rows="3">  
             <apex:column headerValue="Name">  
               <apex:outputLink onclick="return goToDetailPage('{!contact.Id}')" >{!contact.Name}</apex:outputLink>  
             </apex:column>  
             <apex:column value="{!contact.Phone}" headerValue="Phone"/>  
             <apex:column value="{!contact.Department}" headerValue="Department"/>  
           </apex:dataTable>  
           <vs:alert rendered="{!Contacts.empty}" type="warning" style="text-align:center">  
             <vs:glyph icon="exclamation-sign"/> No records to display  
           </vs:alert>  
         </vs:panel>  
       </vs:column>    
     </vs:row>  
   </vs:visualstrapblock>  
 </apex:page>  


Controller


public without sharing class VSDashBoard_Con {  
   public List<Task> getTasks(){  
     return [SELECT Id,Subject,Status, ActivityDate FROM Task WHERE ActivityDate = TODAY AND Status != 'Completed' AND Status != 'Deferred'];  
   }  
   public List<Case> getCases(){  
     return [SELECT Id,CaseNumber,Status,Subject, Priority FROM Case WHERE OwnerId=:UserInfo.getUserId() AND isClosed = FALSE];  
   }  
   public List<Lead> getLeads(){  
     return [SELECT Id,Name,Status, CreatedDate FROM Lead WHERE OwnerId=:UserInfo.getUserId() AND IsUnreadByOwner = true];  
   }  
   public List<Account> getAccounts(){  
     return [SELECT Id,Name,BillingState,Type FROM Account ORDER BY LastViewedDate DESC limit 5 ];  
   }  
   public List<Contact> getContacts(){  
     return [SELECT Id,Name,Phone, Department FROM Contact ORDER BY LastViewedDate DESC limit 5 ];  
   }  
 }  


Deploying the Page to Salesforce1

  • Mark the page VSDashboardS1 "Available for Salesforce mobile apps"

  • Create a Visualforce Tab



  • Add tab to Mobile Navigation Menu




How it looks like on a Mobile Device ?


VSDashboard in the nav menu
The VSDashBoard page
The VSDashBoard page
   
Detail Pages




Monday, February 24, 2014


Well this is the extended version of the app that I blogged few days back. The first version allowed user to see the code coverage in a listview format without going to developer console. Current version 1.2 now allows you to see the "Lines Covered", so now with this update you need not to go to the developer console at all.

This version uses SyntaxHighlighter plugin to highlight the code. You can read more about how this works in this blog.


Features

  • Quickly view the list of class / trigger coverage
  • View the Org wide coverage
  • View the lines covered for a specific class (new in v 1.2)

Some Screens of the actual app

The Apex code coverage list page


The page displaying the covered lines

Monday, February 10, 2014


Since salesforce moved code coverage to developer console, I somehow didn't like it,waited for a while.... and again for like months and no go :( , Salesforce never brought back the old listviews, I was quite missing this  little feature that lets you to have a quick glance of the code coverage. After few weeks finally planned to build something for myself.
This was a great chance to learn a thing or two about Tooling API and a chance to mix some js libraries together to brew something really cool.

After thinking for a while I think these are things I will need to build the page
  • Tooling API : To bring the org code coverage
  • JSRemoting : To bring data to page without the viewstate and in a fast manner
  • JSRender : JsRender is jQuery Templating plugin that lets you create HTML from predefined templates
  • VisualStrap : And the VisualStrap to generate a BootStrap responsive UI for both mobile and desktop
The page in action

Tooling API


The page uses the Tooling API REST service to retrieve the code coverage result.

 private static String sendToolingQueryRequest(String queryStr){  
     HttpRequest req = new HttpRequest();  
     req.setEndpoint(TOOLINGAPI_ENDPOINT+'query/?q='+queryStr);  
     /*Set authorization by using current users session Id*/  
     req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());  
     req.setHeader('Content-Type', 'application/json');      
     req.setMethod('GET');  
     Http http = new Http();  
     HTTPResponse res = http.send(req);  
     return res.getBody();  
   }  


To get the data from the endpoint the method sends the query along with the session id to get the response as JSON string which again used in the JS to render the UI.

{  
   "size": 1,  
   "totalSize": 1,  
   "done": true,  
   "records": [{  
     "attributes": {  
       "type": "ApexCodeCoverage",  
       "url": "/services/data/v29.0/tooling/sobjects/ApexCodeCoverage/71490000002RqOVAA0"  
     },  
     "NumLinesCovered": 2,  
     "ApexClassOrTriggerId": "01p90000001MTXTAA4",  
     "ApexClassOrTrigger": {  
       "attributes": {  
         "type": "Name",  
         "url": "/services/data/v29.0/tooling/sobjects/ApexClass/01p90000001MTXTAA4"  
       },  
       "Name": "jQueryUIBlockDemo_Con"  
     },  
     "NumLinesUncovered": 0  
   }],  
   "queryLocator": null,  
   "entityTypeName": "ApexCodeCoverage"  
 }  


JSRemoting


JSRemoting does the job of bringing the data from controller


JSRender


JSRender takes the job of rendering the data received from the service and use them to generate the table. The templates are pretty easy to handle once you have the data and the decided upon the HTML structure, you can easily create them.

I wanted my page to look like a list so the obvious choice was a table and all the data received should be represented as row, and hence we need a template to generate the rows or "<tr>" for the table. In JSRender JSON data are binded by {{>MY_JSON_FIELDNAME}} 

So the template should be 

<script id="coverageRowTemplate" type="text/x-jsrender">  
     <tr>  
       <td width="20px">  
         <a href="/{{>ApexClassOrTriggerId}}" target="_blank" class="btn btn-xs btn-info"> <span class="glyphicon glyphicon-export"/> view </a>  
       </td>  
       <td>  
         {{>ApexClassOrTrigger.Name}}  
       </td>  
       <td>  
         {{>NumLinesUncovered}}  
       </td>  
       <td>  
         {{>NumLinesCovered}}  
       </td>    
     </tr>  
 </script>

The above template just displays the data received from the remoting method,  lets extend the template to show more info like percentage, totalNumber of lines and may be a background color ?

So to do that we will need some helper methods for the template

$.views.helpers({  
         calculatePercentage: function(NumLinesUncovered,NumLinesCovered){  
           return ((NumLinesCovered/(NumLinesCovered+NumLinesUncovered))*100).toFixed(2);  
         },  
         totalLines:function(NumLinesUncovered,NumLinesCovered){  
           return NumLinesUncovered + NumLinesCovered;  
         },  
         rowStatusClass: function(NumLinesUncovered,NumLinesCovered){  
           var sclass='danger';  
           var percentG = ((NumLinesCovered/(NumLinesCovered+NumLinesUncovered))*100).toFixed(2);  
           if(percentG >= 90){  
             sclass = 'success'  
           }  
           else if(percentG >= 75){  
             sclass = 'warning';  
           }  
           return sclass;  
         }  
 });  

The above code piece defines some helper methods and register them so that they can be used with JSRender templates. So the final template will look like


<script id="coverageRowTemplate" type="text/x-jsrender">  
     <tr class="{{:~rowStatusClass(NumLinesUncovered,NumLinesCovered)}}">  
       <td width="20px">  
         <a href="/{{>ApexClassOrTriggerId}}" target="_blank" class="btn btn-xs btn-info"> <span class="glyphicon glyphicon-export"/> view </a>  
       </td>  
       <td>  
         {{>ApexClassOrTrigger.Name}}  
       </td>  
       <td>  
         {{>NumLinesUncovered}}  
       </td>  
       <td>  
         {{>NumLinesCovered}}  
       </td>  
       <td>  
         {{:~totalLines(NumLinesUncovered,NumLinesCovered)}}  
       </td>        
       <td>  
         {{:~calculatePercentage(NumLinesUncovered,NumLinesCovered )}}  
       </td>  
     </tr>  
   </script>

Now the template serves most of the fields, to generate the HTML 

var html = $( "#JSRENDER_TEMPLATEID" ).render(JSON_DATA );  

and this html can be appended to an existing table in the page to generate a table with the data.

VisualStrap 

VisualStrap is used to generate the Mobile friendly good looking responsive layout along with status classes displayed based on the code coverage percentage

  • Above 90 : Green (css  class = "success")
  • Above 75 : Yellow (css class = "warning")
  • For everything else : Red (css class = "danger")

The mobile layout
So the final product a fast good looking page to view the org code coverage.

Installation : You can follow the project detail link to install a unmanaged package of this page. If you already have visualstrap unmanaged package installed you may have to remove it or you can use source from github to install the same.

VisualForce Page

 <apex:page controller="ApexCodeCoverageList_Con" sidebar="false">  
   <c:importvisualstrap />  
   <apex:includeScript value="{!$Resource.JSRender}"/>  
   <script>  
     function getCodeCoverage(){              
       var rBtn = $('#refreshBtn').button('loading');  
       Visualforce.remoting.Manager.invokeAction(  
         '{!$RemoteAction.ApexCodeCoverageList_Con.fetchCodeCoverage}',  
         function(result,event){  
           if(event.status){  
             console.log(result);  
             var parsedResult = jQuery.parseJSON(result);  
             /*render html using jsrender and attach it to the table*/  
             $('#coverageTableBody').html($( "#coverageRowTemplate" ).render( parsedResult.records ));  
           }  
           else{  
             alert(event.message);  
           }  
           rBtn.button('reset');  
         },  
         {escape: false}  
       );        
     }  
     function getOrgCoverage(){  
       Visualforce.remoting.Manager.invokeAction(  
         '{!$RemoteAction.ApexCodeCoverageList_Con.fetchOrgCoverage}',  
         function(result,event){  
           if(event.status){  
             var parsedResult = jQuery.parseJSON(result);  
             $('#orgCoverage').html(parsedResult.records[0].PercentCovered);  
           }  
           else{  
             alert(event.message);  
           }  
         },  
         {escape: false}  
       );      
     }  
     function getCoverage(){  
       getOrgCoverage();  
       getCodeCoverage();  
     }  
     /*JSrender helper methods*/  
     function initHelperMethods(){  
       $.views.helpers({  
         calculatePercentage: function(NumLinesUncovered,NumLinesCovered){  
           return ((NumLinesCovered/(NumLinesCovered+NumLinesUncovered))*100).toFixed(2);  
         },  
         totalLines:function(NumLinesUncovered,NumLinesCovered){  
           return NumLinesUncovered + NumLinesCovered;  
         },  
         rowStatusClass: function(NumLinesUncovered,NumLinesCovered){  
           var sclass='danger';  
           var percentG = ((NumLinesCovered/(NumLinesCovered+NumLinesUncovered))*100).toFixed(2);  
           if(percentG >= 90){  
             sclass = 'success'  
           }  
           else if(percentG >= 75){  
             sclass = 'warning';  
           }  
           return sclass;  
         }  
       });  
     }  
     $(function(){  
       initHelperMethods();  
       getCoverage();  
     })  
   </script>  
   <!-- JS render template -->  
   <script id="coverageRowTemplate" type="text/x-jsrender">  
     <tr class="{{:~rowStatusClass(NumLinesUncovered,NumLinesCovered)}}">  
       <td width="20px">  
         <a href="/{{>ApexClassOrTriggerId}}" target="_blank" class="btn btn-xs btn-info"> <span class="glyphicon glyphicon-export"/> view </a>  
       </td>  
       <td>  
         {{>ApexClassOrTrigger.Name}}  
       </td>  
       <td>  
         {{>NumLinesUncovered}}  
       </td>  
       <td>  
         {{>NumLinesCovered}}  
       </td>  
       <td>  
         {{:~totalLines(NumLinesUncovered,NumLinesCovered)}}  
       </td>        
       <td>  
         {{:~calculatePercentage(NumLinesUncovered,NumLinesCovered )}}  
       </td>  
     </tr>  
   </script>  
   <c:visualstrapblock >  
     <c:panel type="primary">  
       <center>  
         <c:pageheader icon="cog" title="Apex Code Coverage" subtitle="All Classes"/>  
         <div class="text-muted" style="position:absolute;top:20px;right:20px">Using Tooling API, JS Remoting, JSRender and VisualStrap</div>  
        </center>  
       <apex:outputPanel layout="block" styleClass="well well-sm">  
         <center>  
           <button id="refreshBtn" onclick="getCoverage();return false;" class="btn btn-success" data-loading-text="Refreshing...">  
             <c:glyph icon="refresh"/> Refresh  
           </button>  
         </center>  
       </apex:outputPanel>  
       <apex:outputPanel layout="block" styleClass="row">  
         <apex:outputPanel layout="block" styleClass="col-md-10">  
           <table class="table table-bordered table-striped table-hover table-condensed">  
             <thead>  
               <tr>  
                 <th>  
                   Action  
                 </th>  
                 <th>  
                   Apex Class/ Trigger  
                 </th>  
                 <th>  
                   Lines Not Covered  
                 </th>  
                 <th>  
                   Lines Covered  
                 </th>  
                 <th>  
                   Total Lines  
                 </th>  
                 <th>  
                   Coverage Percentage  
                 </th>  
               </tr>  
             </thead>  
             <tbody id="coverageTableBody">  
             </tbody>  
           </table>  
         </apex:outputPanel>  
         <apex:outputPanel layout="block" styleClass="col-md-2">  
           <vs:panel type="primary" title="Overall Coverage" >  
             <center>  
               <h2 style="font-size:54"><span id="orgCoverage"/> %</h2>  
               <p class="text-muted infolabel">Across all apex classes and triggers</p>   
             </center>  
           </c:panel>  
         </apex:outputPanel>  
       </apex:outputPanel>  
     </c:panel>  
   </c:visualstrapblock>  
 </apex:page>

Apex Class

/*  
 *  @Author : Avi (avidev9@gmail.com)  
 *  @Description : Controller class for ApexCodeCoverageList page, Contains remoted method and method to call tooling api  
 *  
 **/  
 public class ApexCodeCoverageList_Con{  
   private static FINAL String ORG_INSTANCE;  
   private static FINAL String TOOLINGAPI_ENDPOINT;  
   static{  
     ORG_INSTANCE = getInstance();  
     TOOLINGAPI_ENDPOINT = 'https://'+ORG_INSTANCE+'.salesforce.com/services/data/v29.0/tooling/';  
   }  
   @RemoteAction  
   public static String fetchCodeCoverage(){  
     return sendToolingQueryRequest('SELECT+NumLinesCovered,ApexClassOrTriggerId,ApexClassOrTrigger.Name,NumLinesUncovered+FROM+ApexCodeCoverage');  
   }  
   @RemoteAction  
   public static String fetchOrgCoverage(){  
     return sendToolingQueryRequest('SELECT+PercentCovered+FROM+ApexOrgWideCoverage');  
   }  
   /*Method to send query request to tooling api endpoint*/  
   private static String sendToolingQueryRequest(String queryStr){  
     HttpRequest req = new HttpRequest();  
     req.setEndpoint(TOOLINGAPI_ENDPOINT+'query/?q='+queryStr);  
     /*Set authorization by using current users session Id*/  
     req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());  
     req.setHeader('Content-Type', 'application/json');      
     req.setMethod('GET');  
     Http http = new Http();  
     HTTPResponse res = http.send(req);  
     return res.getBody();  
   }  
   /*Method to get org instance*/  
   private static String getInstance(){  
     String instance;  
     List<String> parts = System.URL.getSalesforceBaseUrl().getHost().replace('-api','').split('\\.');  
     if (parts.size() == 3 ) Instance = parts[0];  
     else if (parts.size() == 5 || parts.size() == 4) Instance = parts[1];  
     else Instance = null;  
     return instance;  
   }  
 }  

Wednesday, January 29, 2014


I just seeded a new version of VisualStrap with much more components and added a bit of optimisation to existing css. This blog is more about how you can create your Force.com site page very easily using VisualStrap.

Lets take an example of a site of a Product/Company and talks about its features/offering. The site will be a very simple one, one main block which has the company/product banner and some other small blocks that talks about the features.


The Design


The Design
To achieve the above design we will basically need the following stuff


  • navbar (header & footer)
  • well (for features and some minor items)
  • column (grid)
  • row (grid)
  • jumbotron (Highlighted main panel)


Desktop View

Mobile View (the column type/class "col-md-4" makes the blocks stack on devices with lower screen resolution)

So finally the actual page uses


  • navbar
  • well
  • column (grid)
  • row (grid)
  • button
  • modal
  • glyph
  • jumbotron


The Code


<apex:page showHeader="false" docType="html-5.0" >  
   <vs:importvisualstrap />  
   <style>  
     body{  
         font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;  
       }  
     .intro{  
       margin-top:20px;  
       font-size:140%;  
       font-weight: 200;  
     }  
   </style>  
   <vs:visualstrapblock >  
     <apex:form >  
       <!--header -->  
       <vs:navbar brand="Blogforce9" inverse="true" type="fixed-top">  
         A site about VisualStrap  
       </vs:navbar>  
       <!-- highlighted content -->  
       <apex:outputPanel layout="block" styleClass="container" >  
         <apex:outputPanel layout="block" styleClass="jumbotron" style="text-align:center">  
           <h1><vs:glyph icon="bookmark" style="font-size:75%"/> VisualStrap Demo Site</h1>  
           <p>This is a example how VisualStrap can be used to create a site page. All the standard components can be used inside this page without any problem </p>  
           <apex:commandButton styleClass="btn-lg btn-success" value="Submit Request" html-data-toggle="modal" html-data-target="#newRequest"/>  
         </apex:outputPanel>  
       </apex:outputPanel>  
       <!-- the feature section -->  
       <apex:outputPanel layout="block" styleClass="container" >  
         <apex:outputPanel layout="block" styleClass="row">  
           <apex:outputPanel layout="block" styleClass="col-md-4">  
             <apex:outputPanel layout="block" styleClass="well">  
               <h3>   
                 <vs:glyph icon="cog"/> Optimized  
               </h3>  
               <div class="intro" >VisualStrap is based on Bootstrap 3. It uses a wrapper style class to designate the areas where actual theming using bootstrap is required. VisualStrap CSS is optimized to work with Visualforce pages even with standard stylesheet and header on.</div>  
             </apex:outputPanel>  
           </apex:outputPanel>  
           <apex:outputPanel layout="block" styleClass="col-md-4">  
             <apex:outputPanel layout="block" styleClass="well">  
               <h3>   
                 <vs:glyph icon="retweet"/> Flexible  
               </h3>  
               <div class="intro" >VisualStrap is based on bootstrap there are many components available in the package that can be used to create pages. If are aware about bootstrap components you can directly implement them in page without using components </div>  
             </apex:outputPanel>  
           </apex:outputPanel>  
           <apex:outputPanel layout="block" styleClass="col-md-4">  
             <apex:outputPanel layout="block" styleClass="well">  
               <h3>   
                 <vs:glyph icon="tasks"/> Components  
               </h3>  
               <div class="intro" >There are many components available in the package that makes Bootstrap/VisualStrap implementation inside a page very easy. These components handles most of the styling based on a very familiar syntax</div>  
             </apex:outputPanel>  
           </apex:outputPanel>  
         </apex:outputPanel>  
       </apex:outputPanel>  
       <!-- footer -->  
       <vs:navbar brand="Blogforce9" inverse="true" type="fixed-bottom" layout="none">  
         <center>  
           <apex:outputPanel styleClass="text-muted" style="margin:20px;font-size:130%" layout="block">  
             <vs:glyph icon="bullhorn"/> Site powered by Force.com  
           </apex:outputPanel>  
         </center>  
       </vs:navbar>  
       <!-- the modal form-->  
       <vs:modal title="New Request" id="newRequest">  
         <apex:pageBlock mode="maindetail">  
           <apex:pageBlockSection >  
             <apex:pageBlockSectionItem >  
               <apex:outputLabel >First Name</apex:outputLabel>  
               <apex:input type="text"/>  
             </apex:pageBlockSectionItem>  
             <apex:pageBlockSectionItem >  
               <apex:outputLabel >Last Name</apex:outputLabel>  
               <apex:input type="text"/>  
             </apex:pageBlockSectionItem>  
             <apex:pageBlockSectionItem >  
               <apex:outputLabel >Email</apex:outputLabel>  
               <apex:input type="text"/>  
             </apex:pageBlockSectionItem>  
           </apex:pageBlockSection>  
         </apex:pageBlock>  
         <apex:outputPanel styleClass="modal-footer" layout="block">  
           <apex:commandButton value="Close" styleClass="btn-warning" html-data-dismiss="modal"/>  
           <apex:commandButton value="Save Request" styleClass="btn-success" html-data-dismiss="modal"/>  
         </apex:outputPanel>  
       </vs:modal>  
     </apex:form>  
   </vs:visualstrapblock>  
 </apex:page>


To use the above code you need to install the latest version of VisualStrap from the below link. If you are using the source files from Github to install the components replace the "vs:" in the above code with "c:".

Important Notice : There is a bug in platform related to Managed Package only due to which salesforce is not able to resolve the namespace name properly. I have a ticket raised with salesforce but its still open. Meanwhile if you face issues with it you can use the source from the Github or use the Unmanaged Package


Thursday, January 16, 2014


A bit of Introduction 


PageBlockTableEnhancerADV is a plugin that lets you convert a normal VisualForce pageblock table into a datatable. The component internally uses the Datatables plugin to bring in features like sorting, filtering and pagination.



So what's new ?


So as planned this post is all about File Exports!, Yes files export is being ported from Datatables to PageBlockTableEnhancerADV. To export files PageBlockTableEnhancerADV uses the Datatable plugin TableTools. TableTools is very flexible plugin that hooks in to the Datatables API to give in an amazing set of exporting option.

So this version of PageBlockTableEnhancerADV with the help of TableTools brings in 
  • Export to PDF
  • Export to CSV
  • Export to Excel
  • Printable view
  • Copy to clipboard
If you are not aware about the PageBlockTableEnhancerADV or PageBlockTableEnhancer you can read about the same from the below links

List of Parameters 


  • targetPbTableIds : comma-separated Ids of the target Pageblock tables 
  • paginate : Assign true if you want to use the pagination feature,default value is true.
  • pageSizeOptions : A comma separated list of integer values that will displayed as dropdown for page size
  •  defaultPageSize : Default page size that needs to be selected (at page load).
  • enableExport : Set this option to true to enable export toolbar (new in v2)
  • exportFileName : Default filename to use when a user uses the export feature. (new in v2)

Syntax


<c:PageBlockTableEnhancerADV targetPbTableIds="mid,mid2" paginate="true" defaultPageSize="5" pageSizeOptions="5,10,20,30,40,50,100" enableExport="true" exportFileName="myFile"/> 



Thursday, January 9, 2014


Few days ago I introduced a set of components called "VisualStrap" which will bring the BootStrap to VisualForce pages very easily. VisualStrap is still work in progress , I am adding new components and improving it whenever I get time.

Till now, I was able to document about most of the components but the documentation needs much more than just description rather may be some examples, showing the capability of the package.

Here are some very first examples.

Case Overview Page 


A simple highlight bar style page that gives a quick glance of the Case. This page demonstrates the use of some common VisualStrap components and how VisualStrap grid works.







This page mainly uses the following VisualStrap components

  • row
  • column
  • glyph
  • well
  • panel

<apex:page standardController="Case" sidebar="false" docType="html-5.0">  
   <style>  
     .glow{  
        animation: flashBg 0.9s;  
        -webkit-animation: flashBg 0.9s alternate infinite;  
     }  
     @keyframes flashBg  
     {  
       from {  
           border: 3px solid #ff6161;  
          }  
       to {  
           border: 3px solid #ffd324;  
         }  
     }  
     @-webkit-keyframes flashBg /* Safari and Chrome */  
     {  
       from {  
           border: 3px solid #ff6161;  
          }  
       to {  
           border: 3px solid #ffd324;  
           box-shadow: 0px 0px 50px 3px #e14f1c;  
         }  
     }  
   </style>  
   <vs:importvisualstrap />  
   <vs:visualstrapblock >  
     <vs:panel type="primary" title="Case Overview">  
       <vs:row >  
         <vs:column type="col-md-3">  
           <div class="glow">  
             <vs:well style="text-align:center">                
               <vs:row >  
                 <vs:column type="col-md-4" style="font-size:54px">  
                   <vs:glyph icon="time" style="color:red"/>              
                 </vs:column>  
                 <vs:column type="col-md-8">                  
                   <h2>  
                     {!ROUND(NOW() - Case.CreatedDate,0)}  
                   </h2>  
                   <p class="text-muted infolabel">Days waiting for response</p>              
                 </vs:column>  
               </vs:row>                
             </vs:well>  
           </div>   
         </vs:column>  
         <vs:column type="col-md-3">  
           <vs:well style="text-align:center">  
             <vs:row >  
               <vs:column type="col-md-4" style="font-size:54px">  
                 <vs:glyph icon="flag"/>              
               </vs:column>  
               <vs:column type="col-md-8">                  
                 <h2>  
                   {!Case.Status}  
                 </h2>  
                 <p class="text-muted infolabel">Current case status</p>              
               </vs:column>  
             </vs:row>  
           </vs:well>  
         </vs:column>  
         <vs:column type="col-md-3">  
           <vs:well style="text-align:center">  
             <vs:row >  
               <vs:column type="col-md-4" style="font-size:54px">  
                 <vs:glyph icon="filter"/>              
               </vs:column>  
               <vs:column type="col-md-8">                  
                 <h2>  
                   {!Case.Type}  
                 </h2>  
                 <p class="text-muted infolabel">Case Type</p>              
               </vs:column>  
             </vs:row>  
           </vs:well>  
         </vs:column>  
         <vs:column type="col-md-3">  
           <vs:well style="text-align:center">  
             <vs:row >  
               <vs:column type="col-md-4" style="font-size:54px">  
                 <vs:glyph icon="comment"/>              
               </vs:column>  
               <vs:column type="col-md-8">                  
                 <p>  
                   {!Case.Subject}  
                 </p>  
                 <p class="text-muted infolabel">Subject</p>              
               </vs:column>  
             </vs:row>  
           </vs:well>  
         </vs:column>  
       </vs:row>  
     </vs:panel>  
   </vs:visualstrapblock>  
   <apex:detail title="false"/>  
 </apex:page> 

User Dashboard Page


This page is a simple dashboard that gives user about the daily information that they need.  Like pending activities for the day, assigned cases, assigned leads, last viewed Accounts/contacts. 



[The layout is mobile friendly try opening the link in a iPad or try to scale down your browser window. The blocks will stack according to screen real estate]

This page mainly uses the following VisualStrap components
  • row
  • column
  • glyph
  • alert
  • panel
  • tables
  • well


<apex:page sidebar="false" docType="html-5.0" controller="VSDashBoard_Con">  
   <vs:importvisualstrap />  
   <vs:visualstrapblock >  
     <center>  
       <vs:pageheader title="User Dashboard" icon="calendar" subtitle="{!$User.FirstName} {!$User.LastName}"/>  
     </center>  
     <vs:row >  
       <vs:column type="col-md-4">  
         <vs:panel title="Tasks" type="primary">  
           <vs:well style="text-align:center;">  
              <vs:glyph icon="tasks" style="font-size:40px"/> &nbsp;<span style="font-size:54px">{!Tasks.size}</span>  
              <p class="text-muted">Tasks due for Today</p>  
           </vs:well>  
           <apex:dataTable value="{!Tasks}" var="task" styleClass="table table-condensed table-hover table-bordered" rows="3">  
             <apex:column headerValue="Subject">  
               <apex:outputLink value="/{!task.Id}">{!task.Subject}</apex:outputLink>  
             </apex:column>  
             <apex:column value="{!task.Status}" headerValue="Status"/>  
             <apex:column value="{!task.ActivityDate}" headerValue="Due Date"/>  
           </apex:dataTable>  
           <vs:alert rendered="{!Tasks.empty}" type="success" style="text-align:center">  
             <vs:glyph icon="ok-sign"/> No records to display  
           </vs:alert>  
         </vs:panel>  
       </vs:column>  
       <vs:column type="col-md-4">  
         <vs:panel title="Cases" type="primary">  
           <vs:well style="text-align:center;">  
              <vs:glyph icon="briefcase" style="font-size:40px"/>&nbsp;<span style="font-size:54px">{!Cases.size}</span>  
              <p class="text-muted">Assigned Cases</p>  
           </vs:well>  
           <apex:dataTable value="{!Cases}" var="case" styleClass="table table-condensed table-hover table-bordered" rows="3">  
             <apex:column headerValue="Case Number">  
               <apex:outputLink value="/{!case.Id}">{!case.CaseNumber}</apex:outputLink>  
             </apex:column>  
             <apex:column value="{!case.Status}" headerValue="Status"/>  
             <apex:column value="{!case.Priority}" headerValue="Priority"/>  
           </apex:dataTable>  
           <vs:alert rendered="{!Cases.empty}" type="warning" style="text-align:center">  
             <vs:glyph icon="exclamation-sign"/> No records to display  
           </vs:alert>  
         </vs:panel>  
       </vs:column>  
       <vs:column type="col-md-4">  
         <vs:panel title="Leads" type="primary">  
           <vs:well style="text-align:center;">  
              <vs:glyph icon="user" style="font-size:40px"/>&nbsp;<span style="font-size:54px">{!Leads.size}</span>  
              <p class="text-muted">Unread Leads</p>  
           </vs:well>  
           <apex:dataTable value="{!Leads}" var="lead" styleClass="table table-condensed table-hover table-bordered" rows="3">  
             <apex:column headerValue="Name">  
               <apex:outputLink value="/{!lead.Id}">{!lead.Name}</apex:outputLink>  
             </apex:column>  
             <apex:column value="{!lead.Status}" headerValue="Status"/>  
             <apex:column value="{!lead.CreatedDate}" headerValue="Created Date"/>  
           </apex:dataTable>  
           <vs:alert rendered="{!Leads.empty}" type="warning" style="text-align:center">  
             <vs:glyph icon="exclamation-sign"/> No records to display  
           </vs:alert>  
         </vs:panel>  
       </vs:column>        
     </vs:row>  
     <vs:row >  
       <vs:column type="col-md-6">  
         <vs:panel title="Last Viewed Accounts" type="primary">  
           <apex:dataTable value="{!Accounts}" var="acc" styleClass="table table-condensed table-hover table-bordered" >  
             <apex:column headerValue="Name">  
               <apex:outputLink value="/{!acc.Id}">{!acc.Name}</apex:outputLink>  
             </apex:column>  
             <apex:column value="{!acc.Type}" headerValue="Type"/>  
             <apex:column value="{!acc.BillingState}" headerValue="State"/>  
           </apex:dataTable>  
           <vs:alert rendered="{!Accounts.empty}" type="warning" style="text-align:center">  
             <vs:glyph icon="exclamation-sign"/> No records to display  
           </vs:alert>  
         </vs:panel>  
       </vs:column>  
       <vs:column type="col-md-6">  
         <vs:panel title="Last Viewed Contacts" type="primary">  
           <apex:dataTable value="{!Contacts}" var="contact" styleClass="table table-condensed table-hover table-bordered" rows="3">  
             <apex:column headerValue="Name">  
               <apex:outputLink value="/{!contact.Id}">{!contact.Name}</apex:outputLink>  
             </apex:column>  
             <apex:column value="{!contact.Phone}" headerValue="Phone"/>  
             <apex:column value="{!contact.Department}" headerValue="Department"/>  
           </apex:dataTable>  
           <vs:alert rendered="{!Contacts.empty}" type="warning" style="text-align:center">  
             <vs:glyph icon="exclamation-sign"/> No records to display  
           </vs:alert>  
         </vs:panel>  
       </vs:column>    
     </vs:row>  
   </vs:visualstrapblock>  
 </apex:page>  


 public without sharing class VSDashBoard_Con {  
   public List<Task> getTasks(){  
     return [SELECT Id,Subject,Status, ActivityDate FROM Task WHERE ActivityDate = TODAY AND Status != 'Completed' AND Status != 'Deferred'];  
   }  
   public List<Case> getCases(){  
     return [SELECT Id,CaseNumber,Status,Subject, Priority FROM Case WHERE OwnerId=:UserInfo.getUserId() AND isClosed = FALSE];  
   }  
   public List<Lead> getLeads(){  
     return [SELECT Id,Name,Status, CreatedDate FROM Lead WHERE OwnerId=:UserInfo.getUserId() AND IsUnreadByOwner = true];  
   }  
   public List<Account> getAccounts(){  
     return [SELECT Id,Name,BillingState,Type FROM Account ORDER BY LastViewedDate DESC limit 5 ];  
   }  
   public List<Contact> getContacts(){  
     return [SELECT Id,Name,Phone, Department FROM Contact ORDER BY LastViewedDate DESC limit 5 ];  
   }  
 }  

Please Note : You can use <apex:outputPanel layout="block" styleClass="row"> or <div class="row"> instead of <vs:row>. Similarly you can use <apex:outputPanel layout="block" styleClass="col-md-4"> or <div class="col-md-4"> instead of <vs:column type="col-md-4"> . And you can also use Bootstrap components inside the pages

VisualStrap is not limited to just these two pages, it can be leveraged to do much more. People out there can extend this to do much more ! Visualstrap is available as Managed package and as well as github. You can grab the same from the project detail page.

To make the above examples work you have to install VisualStrap from project page below. "vs" is namespace prefix from the managed package, if you are using the source from github you may have to replace "vs:" with just "c:".