VisualStrap - Exploring Possibilities!

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:".



7 comments:

  1. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Were you able to figure out how to implement the controller ? You can also find the code in the Github link from the project detail.

      Delete
  2. while using vs:importvisualstrap in VF page,it is showing me error, Error: Unknown component vs:importvisualstrap.Though I have the package.

    ReplyDelete
    Replies
    1. Probably you installed unmanaged package instead of managed package. Try replacing "vs:" with "c:" and you should be good

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Hi Avinava, we tried adding the 'Case Overview Page' to our case detail page layout. The page loads nicely when we initially open a case record. However, once the page comes up, it looks like it continues to make requests to the visualforce server,displaying 'waiting for the server' messages. The page continues to hang up until finally the user can no longer do anything on the record detail, even refresh the page in the browser window. We tried using a custom object in place of the case object and we tried using both the managed and unmanaged packages. Do you know what maybe causing this issue and how it can be corrected?

    ReplyDelete
  5. Hi,
    I'm having the same issue as Brett. The user can click on the edit record but they can no longer double click on any field to get it edited. Any advice?

    ReplyDelete