SessionIdPage:
<apex:page > | |
Start_Of_Session_Id{!$Api.Session_ID}End_Of_Session_Id | |
</apex:page> |
UtilsClass:
global class UtilsClass { | |
global static String getSessionIdFromVFPage(PageReference visualforcePage){ | |
String content = visualforcePage.getContent().toString(); | |
Integer s = content.indexOf('Start_Of_Session_Id') + 'Start_Of_Session_Id'.length(), | |
e = content.indexOf('End_Of_Session_Id'); | |
system.debug('Session ID: ' + content.substring(s, e)); | |
return content.substring(s, e); | |
} | |
} |
searchMetadataCntrl:
/* Name: searchMetadataCntrl | |
* Description: This Apex class makes callout to Salesforce Tooling Api and get the metadata information about the objects. | |
* Created Date: 15/06/2018 | |
* LastModifiedDate: 15/06/2018 | |
* Created By: Arun Kumar | |
*/ | |
public class searchMetadataCntrl { | |
@AuraEnabled | |
public static string GetMetaData(string type){ | |
HttpRequest req = new HttpRequest(); | |
String session_id; | |
if(!test.isRunningTest()){ | |
session_id = UtilsClass.getSessionIdFromVFPage(Page.SessionIdPage); | |
} | |
system.debug('Session ID: ' +session_id); | |
req.setHeader('Authorization', 'Bearer ' + session_id); | |
string domainUrl=URL.getSalesforceBaseUrl().toExternalForm(); | |
string endpoint=''; | |
if(type=='ApexClass & ApexTrigger'){ | |
endpoint='select+id,ApexClassOrTrigger.Name,NumLinesCovered,NumLinesUncovered+from+ApexCodeCoverageAggregate'; | |
} | |
else if(type=='ValidationRule'){ | |
endpoint='Select+id,ErrorDisplayField,createdDate,ValidationName+from+ValidationRule'; | |
} | |
else if(type=='WorkflowRule'){ | |
endpoint='Select+id,Name+from+WorkflowRule'; | |
} | |
else if(type=='VisualforcePages'){ | |
endpoint='Select+id,Name,Description,ControllerType,ApiVersion+from+ApexPage'; | |
}else if(type=='Static Resource'){ | |
endpoint='select+id,Name,ContentType+from+StaticResource'; | |
}else if(type=='Email Template'){ | |
endpoint='select+id,Name,UIType+from+EmailTemplate'; | |
}else if(type=='Documents'){ | |
endpoint='select+id,Name,Type,Url+from+Document'; | |
}else if(type=='Visualforce Component'){ | |
endpoint='select+id,name+from+ApexComponent'; | |
} | |
req.setEndpoint(domainUrl+'/services/data/v42.0/tooling/query/?q='+endpoint); | |
req.setMethod('GET'); | |
Http h = new Http(); | |
try{ | |
HttpResponse response = h.send(req); | |
system.debug(response.getBody()); | |
return response.getBody(); | |
} | |
catch(Exception e){ | |
string exceptionString=e.getMessage(); | |
system.debug('Exception: '+exceptionString); | |
return exceptionString; | |
} | |
} | |
} |
SearchMetadataCmp:
<aura:component controller="searchMetadataCntrl" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" > | |
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/> | |
<aura:attribute name="Result" type="Object"/> | |
<aura:attribute name="metadataType" type="string[]"/> | |
<aura:attribute name="selectedMetadata" type="string"/> | |
<aura:attribute name="searchKeyword" type="string"/> | |
<aura:attribute name="unFilteredResult" type="object"/> | |
<aura:handler event="aura:waiting" action="{!c.showSpinner}"/> | |
<aura:handler event="aura:doneWaiting" action="{!c.hideSpinner}"/> | |
<aura:attribute name="Spinner" type="boolean" default="false"/> | |
<aura:attribute name="isApexType" type="boolean" default="false"/> | |
<aura:attribute name="searchPlaceHolder" type="string"/> | |
<aura:attribute name="TotalRecReturned" type="Integer"/> | |
<aura:attribute type="String" name="headerBgColor" /> | |
<aura:attribute type="String" name="bodyBgColor" /> | |
<aura:attribute name="headerTextColor" type="string"/> | |
<aura:attribute name="bodyTextColor" type="string"/> | |
<aura:attribute name="showSettings" type="boolean" default="false"/> | |
<div class="slds"> | |
<div class="slds-page-header slds-theme_shade slds-theme_alert-texture " style="{! 'background-color:' + v.headerBgColor }"> | |
<span style="{! 'color:' + v.headerTextColor }">Metadata Search</span> | |
<!--<a href="" onclick="{!c.toggleSettings}" id="settingIcon"> | |
<lightning:icon iconName="utility:settings" alternativeText="setting" size="xx-small"/> | |
</a>--> | |
</div> | |
<!-- Starting Page--> | |
<div> | |
</div> | |
<!--End--> | |
<div class="bodyPart" style="{! 'background-color:' + v.bodyBgColor }"> | |
<div style="{! 'color:' + v.bodyTextColor }"> | |
<lightning:select name="selectItem" label="Select an item" onchange="{!c.OnSelectChange}"> | |
<aura:iteration items="{!v.metadataType}" var="m"> | |
<option value="{!m}" label="{!m}" /> | |
</aura:iteration> | |
</lightning:select> | |
<lightning:input label="Search" placeholder="{!v.searchPlaceHolder}" value="{!v.searchKeyword}" onkeyup="{!c.SearchMethod}"></lightning:input> | |
<br/> | |
<aura:if isTrue="{!v.Spinner}"> | |
<div aura:id="spinnerId" class="slds-spinner_container"> | |
<div class="slds-spinner--brand slds-spinner slds-spinner--large slds-is-relative" role="alert"> | |
<span class="slds-assistive-text">Loading</span> | |
<div class="slds-spinner__dot-a"></div> | |
<div class="slds-spinner__dot-b"></div> | |
</div> | |
</div> | |
</aura:if> | |
<aura:if isTrue="{!v.Result !=null}"> | |
<div class="slds-table--header-fixed_container hdr_container" style=" "> | |
<div class="searchResult"> | |
<table class="slds-table slds-table--bordered slds-max-medium-table_stacked-horizontal slds-table--header-fixed" aura:id="myTable"> | |
<thead> | |
<tr class="slds-text-title_caps"> | |
<th class="" scope="col"> | |
<div class="slds-truncate slds-cell-fixed thdr" title="Name">Name</div> | |
</th> | |
<th class=""> | |
<div class="slds-truncate slds-cell-fixed thdr" title="ID">ID</div> | |
</th> | |
<aura:if isTrue="{!v.isApexType}"> | |
<th class="slds-cell-shrink" scope="col"> | |
<div class="slds-truncate slds-cell-fixed thdr" title="Type">Type</div> | |
</th> | |
<th class="" scope="col"> | |
<div class="slds-truncate slds-cell-fixed thdr" title="NumLines Covered">Lines Cov.</div> | |
</th> | |
<th class="" scope="col"> | |
<div class="slds-truncate slds-cell-fixed thdr" title="NumLines Uncovered">Lines Uncov.</div> | |
</th> | |
</aura:if> | |
</tr> | |
</thead> | |
<tbody> | |
<aura:iteration items="{!v.Result}" var="r"> | |
<tr class="slds-hint-parent trow" > | |
<td class="slds-cell-shrink" data-label="Select Row"><a aura:id="trow" href="" id="{!r.Id}" onclick="{!c.navigate}">{!r.Name}</a></td> | |
<td class="slds-cell-shrink" data-label="Select Row">{!r.Id}</td> | |
<td class="slds-cell-shrink" data-label="Select Row">{!r.Type}</td> | |
<td class="slds-cell-shrink" data-label="Select Row">{!r.NumLinesCovered}</td> | |
<td class="slds-cell-shrink" data-label="Select Row">{!r.NumLinesUncovered}</td> | |
</tr> | |
</aura:iteration> | |
</tbody> | |
</table> | |
</div> | |
</div> | |
<br/> | |
<p> Total {!v.TotalRecReturned} Records Returned.</p> | |
</aura:if> | |
</div> | |
</div> | |
</div> | |
</aura:component> |
SearchMetadataCmpController:
({ | |
doInit : function(component, event, helper) { | |
var type=['ApexClass & ApexTrigger','ValidationRule','WorkflowRule','VisualforcePages','Static Resource','Email Template','Documents','Visualforce Component']; | |
component.set("v.metadataType",type); | |
component.set("v.selectedMetadata",'ApexClass & ApexTrigger'); | |
helper.GetSearchedData(component,event,helper); | |
}, | |
OnSelectChange:function(component,event,helper){ | |
var selected=event.getSource().get("v.value"); | |
console.log('selectted: ' +selected); | |
component.set("v.searchPlaceHolder",'Search '+selected); | |
component.set("v.selectedMetadata",selected); | |
if(selected=='--None--'){ | |
component.set("v.Result",null); | |
}else{ | |
helper.GetSearchedData(component,event,helper); | |
} | |
}, | |
showSpinner: function(component, event, helper) { | |
component.set("v.Spinner", true); | |
}, | |
hideSpinner : function(component,event,helper){ | |
component.set("v.Spinner", false); | |
}, | |
navigate:function(component,event,helper){ | |
var idx = event.target.id; | |
var urlEvent = $A.get("e.force:navigateToURL"); | |
urlEvent.setParams({ | |
"url": "/"+idx, | |
"target": "_blank" | |
}); | |
urlEvent.fire(); | |
}, | |
SearchMethod:function(component,event,helper){ | |
var searchKeyWord=event.getSource().get("v.value"); | |
if(searchKeyWord!=''){ | |
helper.SearchItems(component,event,searchKeyWord); | |
}else{ | |
component.set("v.Result",component.get("v.unFilteredResult")); | |
} | |
} | |
}) |
SearchMetadataCmpHelper:
({ | |
GetSearchedData : function(component,event,helper) { | |
var action=component.get("c.GetMetaData"); | |
var selectedType=component.get("v.selectedMetadata"); | |
action.setParams({ | |
"type": component.get("v.selectedMetadata") | |
}); | |
action.setCallback(this,function(response){ | |
var state=response.getState(); | |
if(state=='SUCCESS'){ | |
var result=JSON.parse(response.getReturnValue()); | |
var returnedString = JSON.stringify(response.getReturnValue()); | |
if(returnedString.includes("Unauthorized endpoint, please check Setup")){ | |
//alert('Unauthorized end point'); | |
var sMsg ='Unauthorized endpoint, please goto Setup->Security->Remote site settings '; | |
sMsg+='and add a remote site setting (endpoint = https://your_domain-dev-ed.my.salesforce.com/)'; | |
var toastEvent = $A.get("e.force:showToast"); | |
toastEvent.setParams({ | |
mode: 'sticky', | |
message: sMsg, | |
type : 'warning' | |
}); | |
toastEvent.fire(); | |
} | |
else{ | |
console.log('result size: ' +result.size); | |
console.log('result: '+ JSON.stringify(result)); | |
component.set("v.TotalRecReturned",result.size); | |
var arrayData=new Array(); | |
if(selectedType=='ApexClass & ApexTrigger'){ | |
component.set("v.isApexType",true); | |
for(var i=0; i<result.records.length;i++){ | |
if(result.records[i].ApexClassOrTrigger !=null){ | |
var str=result.records[i].ApexClassOrTrigger.attributes.url; | |
var rest = str.substring(0, str.lastIndexOf("/") ); | |
var Ids = str.substring(str.lastIndexOf("/") + 1, str.length); | |
var mType = rest.substring(rest.lastIndexOf("/") + 1, rest.length); | |
var obj={"Id":Ids, | |
"Name":result.records[i].ApexClassOrTrigger.Name.toUpperCase(), | |
"Type":mType, | |
"NumLinesCovered":result.records[i].NumLinesCovered, | |
"NumLinesUncovered":result.records[i].NumLinesUncovered}; | |
arrayData.push(obj); | |
component.set("v.Result",arrayData); | |
component.set("v.unFilteredResult",arrayData); | |
} | |
} | |
} | |
if(selectedType=='ValidationRule'){ | |
component.set("v.isApexType",false); | |
for(var i=0; i<result.records.length;i++){ | |
var obj={"Id":result.records[i].Id, | |
"Name":result.records[i].ValidationName, | |
"TableEnumOrId":result.records[i].ValidationName} | |
arrayData.push(obj); | |
} | |
component.set("v.Result",arrayData); | |
component.set("v.unFilteredResult",arrayData); | |
} | |
if(selectedType=='WorkflowRule'){ | |
component.set("v.isApexType",false); | |
for(var i=0; i<result.records.length;i++){ | |
var obj={"Id":result.records[i].Id, | |
"Name":result.records[i].Name, | |
"TableEnumOrId":result.records[i].TableEnumOrId} | |
arrayData.push(obj); | |
} | |
component.set("v.Result",arrayData); | |
component.set("v.unFilteredResult",arrayData); | |
} | |
if(selectedType=='VisualforcePages'){ | |
component.set("v.isApexType",false); | |
for(var i=0; i<result.records.length;i++){ | |
var obj={"Id":result.records[i].Id, | |
"Name":result.records[i].Name, | |
} | |
arrayData.push(obj); | |
} | |
component.set("v.Result",arrayData); | |
component.set("v.unFilteredResult",arrayData); | |
} | |
if(selectedType=='Static Resource'){ | |
component.set("v.isApexType",false); | |
for(var i=0; i<result.records.length;i++){ | |
var obj={"Id":result.records[i].Id, | |
"Name":result.records[i].Name.toUpperCase(), | |
} | |
arrayData.push(obj); | |
} | |
component.set("v.Result",arrayData); | |
component.set("v.unFilteredResult",arrayData); | |
} | |
if(selectedType=='Email Template'){ | |
component.set("v.isApexType",false); | |
for(var i=0; i<result.records.length;i++){ | |
var obj={"Id":result.records[i].Id, | |
"Name":result.records[i].Name.toUpperCase(), | |
} | |
arrayData.push(obj); | |
} | |
component.set("v.Result",arrayData); | |
component.set("v.unFilteredResult",arrayData); | |
} | |
if(selectedType=='Documents'){ | |
component.set("v.isApexType",false); | |
for(var i=0; i<result.records.length;i++){ | |
var obj={"Id":result.records[i].Id, | |
"Name":result.records[i].Name.toUpperCase(), | |
} | |
arrayData.push(obj); | |
} | |
component.set("v.Result",arrayData); | |
component.set("v.unFilteredResult",arrayData); | |
} | |
if(selectedType=='Visualforce Component'){ | |
component.set("v.isApexType",false); | |
for(var i=0; i<result.records.length;i++){ | |
var obj={"Id":result.records[i].Id, | |
"Name":result.records[i].Name.toUpperCase(), | |
} | |
arrayData.push(obj); | |
} | |
component.set("v.Result",arrayData); | |
component.set("v.unFilteredResult",arrayData); | |
} | |
} | |
} | |
}); | |
$A.enqueueAction(action); | |
}, | |
SearchItems:function(component,event,searchKey){ | |
console.log('Search Key: ' +searchKey); | |
var arrayForSearch=component.get("v.Result"); | |
var NameArray=new Array(); | |
for(var i=0; i<arrayForSearch.length; i++){ | |
var obj={"Id":arrayForSearch[i].Id, | |
"Name":arrayForSearch[i].Name.toUpperCase(), | |
"Type":arrayForSearch[i].Type, | |
"NumLinesCovered":arrayForSearch[i].NumLinesCovered, | |
"NumLinesUncovered":arrayForSearch[i].NumLinesUncovered}; | |
NameArray.push(obj); | |
} | |
var resultArray=new Array(); | |
for (var j=0; j<NameArray.length; j++) { | |
if(searchKey!=''){ | |
if (NameArray[j].Name.toString().match (searchKey.toUpperCase())) | |
{ | |
console.log('Matching: '); | |
resultArray.push(NameArray[j]); | |
component.set("v.Result",resultArray); | |
} | |
} | |
else{ | |
} | |
} | |
} | |
}) |
SearchMetadataCmpCSS:
.THIS .changeMe{ | |
display: ""; | |
color:red; | |
background-color:yellow; | |
} | |
.THIS .ul_list{ | |
padding:10px; | |
} | |
.THIS .slds-page-header { | |
border-radius: 0px; | |
} | |
.THIS .RemoveMe{ | |
display: "none"; | |
} | |
.THIS .bodyPart{ | |
background-color:white; | |
padding:10px 10px 10px 10px; | |
} | |
.THIS .trow{ | |
height:35px; | |
} | |
.THIS .thdr{ | |
padding-top: 1.5%; | |
padding-left: 1%; | |
} | |
.THIS .searchResult{ | |
height:200px; | |
overflow-y: scroll; | |
border-radius:3px; | |
} | |
.THIS .hdr_container { | |
padding-top: 5%; | |
} | |
.THIS #settingIcon{ | |
float:right; | |
} | |
.THIS #settingDrpdwn{ | |
position: relative; | |
float: right; | |
right: 22%; | |
top: -2px; | |
} | |
.THIS .menu{ | |
width: 194px; | |
padding: 10px; | |
} | |
.THIS .slds-page-header{ | |
border-radius:none; | |
} |
Find the code on github here.
Happy Coding… 🙂
Thanks
Arun Kumar