function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
uHaveOptionsuHaveOptions 

List View based on Activities in Contacts or any object

Question to my great developers. What route should I take on this project.

Just like every other list view in Salesforce, I know that the activity history are not shown in any field or even creating a filter for it.  

SCENARIO:
Create a List View of contacts that will show and filter Activity History "Subject" and "Call Result" and "Date"
Ex. 
John Doe - Subject: Call - Call Result: Reached

The reason for this is to have a call list for my Salesteam and be able to do it in any standard/custom object.  Also have it sorted by the newest date on top so once a new call date has been made it goes all the way to the bottom of the list.

- Visualforce? Can you show code?
- Process Builder? Can you guide the process
- Field Creation? What formula?

Can you guys share your thoughts and codes so I can try?
Best Answer chosen by uHaveOptions
Siddharth ManiSiddharth Mani
There are 2 ways to approach this. First is using javascript which I found using the link:
http://codebug.eu/?p=30
This will work for records that are being currently displayed on the VF Page and will give you dynamic results. Below is the edited code (Controller code remains the same):
<apex:page controller="contactActivityHistory">
<!-- Jquery -->
<apex:includeScript value="//code.jquery.com/jquery-1.11.3.min.js"/>
<apex:stylesheet value="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css"/>
 
<!-- DataTable -->
<apex:includeScript value="//cdn.datatables.net/1.10.9/js/jquery.dataTables.min.js"/>
<apex:stylesheet value="//cdn.datatables.net/1.10.9/css/jquery.dataTables.min.css"/>
 
<!-- Search Highlight -->
<apex:includeScript value="//bartaz.github.io/sandbox.js/jquery.highlight.js"/>
<apex:includeScript value="//cdn.datatables.net/plug-ins/1.10.9/features/searchHighlight/dataTables.searchHighlight.min.js"/>
<apex:stylesheet value="//cdn.datatables.net/plug-ins/1.10.9/features/searchHighlight/dataTables.searchHighlight.css"/>

<style>
.filterMatches{
  background-color: #BFFF00;
}
.tertiaryPalette{
  color: #000 !important;
}
.dt-buttons{
  margin-left: 10px;
}
</style>

<script type="text/javascript">
$(document).ready(function(){
  
 var accountsTable = $('[cid$="actTable"]').parent('table').eq(0).DataTable({
   //enables results highlight
   searchHighlight: true,
   //sets record lengths to show in picklist
   aLengthMenu: [
     [10, 25, 50, 100, 200, -1],
     [10, 25, 50, 100, 200, "All"]
   ],
   "iDisplayLength": 10,
   //adds copy, print buttons...
   dom: 'lBfrtip', //l=length, B=buttons, f=filter(search), r=processing, t=the table, I=table summary, p=page controls
   buttons: [
     'copy', 'csv', 'excel', 'pdf',
     {
       extend: 'print',
       customize: function(win) {
         $(win.document.body)
         .css( 'font-size', '10pt' )
         .prepend('<img src="http://datatables.net/media/images/logo-fade.png" style="position:absolute; top:0; left:0;" />');
 
         $(win.document.body).find( 'table' )
         .addClass( 'compact' )
         .css( 'font-size', 'inherit' );
       }
     }
   ],
 });
 
});
</script>

  <apex:pageBlock title="Activity History">
      <apex:pageBlockSection >
          <apex:pageBlockTable value="{!ListTasks}" var="tsk" html-cid="actTable">
              <apex:column headerValue="Contact" value="{!tsk.WhoId}"/>
              <apex:column headerValue="Subject" value="{!tsk.Subject}" />
              <apex:column headerValue="Status" value="{!tsk.Status}"/>
              <apex:column headerValue="Modified Date" value="{!tsk.LastModifiedDate}"/>
          </apex:pageBlockTable>
      </apex:pageBlockSection>  
  </apex:pageBlock>
</apex:page>

Second approach is using Apex changes ie change in controller code. Using this you will be able to search the entire database and the results wont be restricted to the number of records currently being displayed. Below is the edited code for Page and Controller:
Controller:
public class contactActivityHistory {
    
    public Boolean fetchCalled{get;set;}
    public String taskList{get;set;}
    public String status{get;set;}
    public String subject{get;set;}
    
    public contactActivityHistory() {
        fetchCalled = false;
    }
    
    public void fetch() {
        taskList = 'SELECT WHOID, Subject, Status, LastModifiedDate FROM Task WHERE Status LIKE \'%'+status+'%\'';
        List<Task> tskList = Database.query(taskList);
        fetchCalled = true;
    }

    public Task[] getListTasks() {
			List<Contact> cntct = [SELECT Id, Name FROM Contact];
        	List<Id> contactIds = new List<Id>();
        	for(Contact cn : cntct) {
                contactIds.add(cn.Id);
        	}
               	
        if (fetchCalled) {
        	fetch();
    	}
        
        else {
			taskList = 'select whoid,subject,status,LastModifiedDate from task where whoid in : contactIds order by LastModifiedDate desc';    
        }
        List<Task> tskList = Database.query(taskList);
		return tskList;            
    }
}
VF Page:
<apex:page controller="contactActivityHistory">
<apex:form >
      <apex:pageBlock title="Filter">
          <apex:pageBlockButtons >
          <apex:commandButton value="Fetch" action="{!fetch}" reRender="pagination"/>
      </apex:pageBlockButtons>
          <apex:pageBlockSection >
              <apex:inputText value="{!status}" label="Status"/>
          </apex:pageBlockSection>
      </apex:pageBlock>
      <apex:pageBlock title="Activity History" id="pagination">
      <apex:pageBlockSection >
          <apex:pageBlockTable value="{!ListTasks}" var="tsk">
              <apex:column headerValue="Contact" value="{!tsk.WhoId}"/>
              <apex:column headerValue="Subject" value="{!tsk.Subject}" />
              <apex:column headerValue="Status" value="{!tsk.Status}"/>
              <apex:column headerValue="Modified Date" value="{!tsk.LastModifiedDate}"/>
          </apex:pageBlockTable>
      </apex:pageBlockSection>  
  </apex:pageBlock>
</apex:form>
</apex:page>
You can of course add multiple filters here as well and change the controller and page code as desired.

Hope this helps!!

 

All Answers

Siddharth ManiSiddharth Mani
This is the most simplified version that I could come up with. It uses only standard Objects and Fields. Below is the code for VF page and controller:

Visualforce Page:
<apex:page controller="contactActivityHistory">
  <apex:pageBlock title="Activity History">
      <apex:pageBlockSection >
          <apex:pageBlockTable value="{!ListTasks}" var="tsk">
              <apex:column headerValue="Contact" value="{!tsk.WhoId}"/>
              <apex:column headerValue="Subject" value="{!tsk.Subject}"/>
              <apex:column headerValue="Status" value="{!tsk.Status}"/>
              <apex:column headerValue="Modified Date" value="{!tsk.LastModifiedDate}"/>
          </apex:pageBlockTable>
      </apex:pageBlockSection>  
  </apex:pageBlock>
</apex:page>
Controller:
public class contactActivityHistory {
    public Task[] getListTasks() {
        List<Contact> cntct = [SELECT Id, Name FROM Contact];
        List<Id> contactIds = new List<Id>();
        for(Contact cn : cntct) {
            contactIds.add(cn.Id);
        }
        
        List<Task> tskList = [select whoid,subject,status,LastModifiedDate from task where whoid in : contactIds order by LastModifiedDate desc];    
        return tskList;
    }
    
    
}
Let me know if this helps!


 
uHaveOptionsuHaveOptions

@siddharth Mani

How can I filter the Subject and Call Result?

Siddharth ManiSiddharth Mani
There are 2 ways to approach this. First is using javascript which I found using the link:
http://codebug.eu/?p=30
This will work for records that are being currently displayed on the VF Page and will give you dynamic results. Below is the edited code (Controller code remains the same):
<apex:page controller="contactActivityHistory">
<!-- Jquery -->
<apex:includeScript value="//code.jquery.com/jquery-1.11.3.min.js"/>
<apex:stylesheet value="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css"/>
 
<!-- DataTable -->
<apex:includeScript value="//cdn.datatables.net/1.10.9/js/jquery.dataTables.min.js"/>
<apex:stylesheet value="//cdn.datatables.net/1.10.9/css/jquery.dataTables.min.css"/>
 
<!-- Search Highlight -->
<apex:includeScript value="//bartaz.github.io/sandbox.js/jquery.highlight.js"/>
<apex:includeScript value="//cdn.datatables.net/plug-ins/1.10.9/features/searchHighlight/dataTables.searchHighlight.min.js"/>
<apex:stylesheet value="//cdn.datatables.net/plug-ins/1.10.9/features/searchHighlight/dataTables.searchHighlight.css"/>

<style>
.filterMatches{
  background-color: #BFFF00;
}
.tertiaryPalette{
  color: #000 !important;
}
.dt-buttons{
  margin-left: 10px;
}
</style>

<script type="text/javascript">
$(document).ready(function(){
  
 var accountsTable = $('[cid$="actTable"]').parent('table').eq(0).DataTable({
   //enables results highlight
   searchHighlight: true,
   //sets record lengths to show in picklist
   aLengthMenu: [
     [10, 25, 50, 100, 200, -1],
     [10, 25, 50, 100, 200, "All"]
   ],
   "iDisplayLength": 10,
   //adds copy, print buttons...
   dom: 'lBfrtip', //l=length, B=buttons, f=filter(search), r=processing, t=the table, I=table summary, p=page controls
   buttons: [
     'copy', 'csv', 'excel', 'pdf',
     {
       extend: 'print',
       customize: function(win) {
         $(win.document.body)
         .css( 'font-size', '10pt' )
         .prepend('<img src="http://datatables.net/media/images/logo-fade.png" style="position:absolute; top:0; left:0;" />');
 
         $(win.document.body).find( 'table' )
         .addClass( 'compact' )
         .css( 'font-size', 'inherit' );
       }
     }
   ],
 });
 
});
</script>

  <apex:pageBlock title="Activity History">
      <apex:pageBlockSection >
          <apex:pageBlockTable value="{!ListTasks}" var="tsk" html-cid="actTable">
              <apex:column headerValue="Contact" value="{!tsk.WhoId}"/>
              <apex:column headerValue="Subject" value="{!tsk.Subject}" />
              <apex:column headerValue="Status" value="{!tsk.Status}"/>
              <apex:column headerValue="Modified Date" value="{!tsk.LastModifiedDate}"/>
          </apex:pageBlockTable>
      </apex:pageBlockSection>  
  </apex:pageBlock>
</apex:page>

Second approach is using Apex changes ie change in controller code. Using this you will be able to search the entire database and the results wont be restricted to the number of records currently being displayed. Below is the edited code for Page and Controller:
Controller:
public class contactActivityHistory {
    
    public Boolean fetchCalled{get;set;}
    public String taskList{get;set;}
    public String status{get;set;}
    public String subject{get;set;}
    
    public contactActivityHistory() {
        fetchCalled = false;
    }
    
    public void fetch() {
        taskList = 'SELECT WHOID, Subject, Status, LastModifiedDate FROM Task WHERE Status LIKE \'%'+status+'%\'';
        List<Task> tskList = Database.query(taskList);
        fetchCalled = true;
    }

    public Task[] getListTasks() {
			List<Contact> cntct = [SELECT Id, Name FROM Contact];
        	List<Id> contactIds = new List<Id>();
        	for(Contact cn : cntct) {
                contactIds.add(cn.Id);
        	}
               	
        if (fetchCalled) {
        	fetch();
    	}
        
        else {
			taskList = 'select whoid,subject,status,LastModifiedDate from task where whoid in : contactIds order by LastModifiedDate desc';    
        }
        List<Task> tskList = Database.query(taskList);
		return tskList;            
    }
}
VF Page:
<apex:page controller="contactActivityHistory">
<apex:form >
      <apex:pageBlock title="Filter">
          <apex:pageBlockButtons >
          <apex:commandButton value="Fetch" action="{!fetch}" reRender="pagination"/>
      </apex:pageBlockButtons>
          <apex:pageBlockSection >
              <apex:inputText value="{!status}" label="Status"/>
          </apex:pageBlockSection>
      </apex:pageBlock>
      <apex:pageBlock title="Activity History" id="pagination">
      <apex:pageBlockSection >
          <apex:pageBlockTable value="{!ListTasks}" var="tsk">
              <apex:column headerValue="Contact" value="{!tsk.WhoId}"/>
              <apex:column headerValue="Subject" value="{!tsk.Subject}" />
              <apex:column headerValue="Status" value="{!tsk.Status}"/>
              <apex:column headerValue="Modified Date" value="{!tsk.LastModifiedDate}"/>
          </apex:pageBlockTable>
      </apex:pageBlockSection>  
  </apex:pageBlock>
</apex:form>
</apex:page>
You can of course add multiple filters here as well and change the controller and page code as desired.

Hope this helps!!

 
This was selected as the best answer
uHaveOptionsuHaveOptions
Thanks Brother.  I will try this out.  
uHaveOptionsuHaveOptions

@siddharth

A couple of question if you can answer them.
- I added a filter but doesnt seems to search on subject as a tests.
<apex:inputText value="{!Subject}" label="Subject"/>
- I was able to put the sidebar="false" to remove the options on the side, but can I can actually put the search on the sidebar?
- I'm assuming this is only for ActivityHistory? Can I link a field from a different custom object that is searchable too?
- Finally, uploading the VF & Apex from inbound change set gave me a code error that its only 70%.  How can I test this so maybe I can change the code?

Thanks again

 

Siddharth ManiSiddharth Mani
Uhm..Not sure what could be the issue. The code I provided is fully functional on a Developer Org without creating any additional Objects / Fields etc. You can just copy paste the page and controller and see if it works (it should!!). If youa re talking about the first approach, then the dynamic filtering happens only on the pageblocktable and has nothing to do with the sidebar of the VF Page. It will highlight any text that you type in the search bar if its available in any column of the pageblocktable (note that the pageblocktable has a html-cid attribute and by referencing this the whole javascript / jquery works).

If you are talking about the second approach though, you will have to change the controller code as well and not only add an inputtext on the vf page. Check the flow like this:
Button pressed -> fetch method called -> method executes query -> results from query go to the tskList -> pageblock gets rerendered -> updated results are displayed

So essentially when you add a new inputtext on the page for a different filter (or maybe combine both filters), you would need to change the controller code (most importantly the query being executed) so that the results contain the updated list to be displayed. Just remember that the pageblocktable is only displaying whatever is there on "tskList" varialbe in the controller. If you are able to backtrack the same, you will be able to modify the controller and page to suit your needs.

For the second part of your question, I have no idea how to test this yet. Even I am new to salesforce and apex and dont have much exposure to the testing part. Just a suggestion though -> Open developer console and check the red lines which are not getting covered by your test class -> You can then work only on those parts specifically and search around as to how to cover those lines in your code.

Hope it helps!!