Created
April 22, 2022 16:29
-
-
Save dcinzona/381f9caadd86d6560e6b88699f945759 to your computer and use it in GitHub Desktop.
Visualforce Page Metrics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
- Created by gtandeciarz on 6/21/17. | |
--> | |
<apex:page id="VisualForcePageUsage" | |
title="VisualForce Page Metrics" | |
readOnly="true" | |
standardStylesheets="false" | |
> | |
<!-- | |
standardStylesheets="false" | |
applyHtmlTag="false" | |
applyBodyTag="false" | |
showHeader="false" | |
--> | |
<apex:slds /> | |
<script type="text/javascript"> | |
var __sfdcSessionId = '{!GETSESSIONID()}'; | |
function inLightningExperience() { | |
var userTheme = '{!$User.UITheme}'; | |
return ['Theme4d', 'Theme4u'].indexOf('{!$User.UIThemeDisplayed}') > -1; | |
} | |
</script> | |
<script src="/soap/ajax/40.0/connection.js" | |
type="text/javascript"></script> | |
<script type="text/javascript"> | |
var config={ | |
pages : [], | |
sortKey : 'Views', | |
sortOrder : 'desc', | |
since : 'LAST_WEEK' | |
}; | |
var sortClass = 'slds-is-sorted'; | |
function sortedDirClass() { | |
return sortClass + '_' + config.sortOrder; | |
} | |
function getMetrics() | |
{ | |
config.pages = []; | |
var metricsById = {}; | |
var whereClause = config.since == 'All Time' ? '' : `WHERE MetricsDate >= ${config.since}`; | |
var query = `SELECT ApexPageId, ApexPage.Name, SUM(DailyPageViewCount) FROM VisualforceAccessMetrics ${whereClause} group by ApexPageId, ApexPage.Name ORDER BY SUM(DailyPageViewCount) DESC`; | |
var result = sforce.connection.query(query); | |
var it = new sforce.QueryResultIterator(result); | |
while(it.hasNext()) { | |
var record = it.next(); | |
metricsById[record.Name] = record.expr0; | |
console.log('Got record ' + JSON.stringify(record, null, 4)); | |
} | |
var allPages = sforce.connection.query("Select Id, Name, CreatedDate, LastModifiedDate, LastModifiedBy.Name, LastModifiedBy.Id from ApexPage order by Name desc"); | |
var pageIt = new sforce.QueryResultIterator(allPages); | |
while(pageIt.hasNext()) { | |
var record = pageIt.next(); | |
var ct = metricsById[record.Name] != undefined ? metricsById[record.Name] : 0; | |
var lastmoduser = record.LastModifiedBy; | |
if(lastmoduser){ | |
console.log(lastmoduser['Name']); | |
} | |
var page = { Id: record.Id, | |
Name : record.Name, | |
CreatedDate : record.CreatedDate, | |
Views : parseInt(ct), | |
LastModifiedDate : record.LastModifiedDate, | |
LastModifiedBy : lastmoduser ? lastmoduser['Name'] : '', | |
LastModifiedById : lastmoduser ? lastmoduser['Id'] : '' | |
}; | |
config.pages.push(page); | |
} | |
renderPages(); | |
var formData = document.querySelector('div[id="formData"]'); | |
formData.setAttribute('style',''); | |
} | |
function renderPages(){ | |
var output=''; | |
var sorted = config.pages.sort(compareValues(config.sortKey,config.sortOrder)); | |
for(var prop in sorted){ | |
var page = sorted[prop]; | |
output+=`<tr> | |
<th scope="row" data-label="${prop}"><div class="slds-truncate" title="${page.Name}"><a href="/${page.Id}">${page.Name}</a></div></th> | |
<td class="${page.Views == 0 ? 'slds-text-color_error' : ''}"><div class="slds-truncate" title="${page.Views}">${page.Views}</div></td> | |
<td><div class="slds-truncate" title="${convertDate(page.CreatedDate)}">${convertDate(page.CreatedDate)}</div></td> | |
<td><div class="slds-truncate" title="${convertDate(page.LastModifiedDate)}">${convertDate(page.LastModifiedDate)}</div></td> | |
<td><div class="slds-truncate" title="${page.LastModifiedBy}"><a href="/${page.LastModifiedById}">${page.LastModifiedBy}</a></div></td> | |
</tr>`; | |
//console.log(JSON.stringify(page, null, 4)); | |
} | |
document.getElementById('output').innerHTML=output; | |
} | |
function convertDate(inputFormat) { | |
function pad(s) { return (s < 10) ? '0' + s : s; } | |
var d = new Date(inputFormat); | |
return [ pad(d.getMonth()+1),pad(d.getDate()), d.getFullYear()].join('/'); | |
} | |
// function for dynamic sorting | |
function compareValues(key, order) { | |
order = order != undefined ? order : 'asc'; | |
return function(a, b) { | |
if(!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) { | |
// property doesn't exist on either object | |
return 0; | |
} | |
const varA = (typeof a[key] === 'string') ? | |
a[key].toUpperCase() : a[key]; | |
const varB = (typeof b[key] === 'string') ? | |
b[key].toUpperCase() : b[key]; | |
var comparison = 0; | |
if (varA > varB) { | |
comparison = 1; | |
} else if (varA < varB) { | |
comparison = -1; | |
} | |
return ( | |
(order == 'desc') ? (comparison * -1) : comparison | |
); | |
}; | |
} | |
document.addEventListener('DOMContentLoaded',function() { | |
var sel = document.querySelector('select[id="filterSince"]'); | |
sel.onchange=changeEventHandler; | |
sel.value = config.since; | |
getMetrics(); | |
},false); | |
function changeEventHandler(event) { | |
// You can use “this” to refer to the selected element. | |
var val = event.target.value; | |
console.log(val); | |
config.since = val; | |
getMetrics(); | |
} | |
function resetSortUI(){ | |
var selector ='.' + sortClass + ', .' + sortedDirClass(); | |
var list = document.querySelectorAll(selector); | |
for (var item of list) { | |
item.classList.remove(sortClass,sortedDirClass()); | |
} | |
} | |
function sortBy(elem, key, order){ | |
resetSortUI(); | |
if(config.sortKey === key){ | |
config.sortOrder = config.sortOrder === 'asc' ? 'desc' : 'asc'; | |
}else{ | |
config.sortKey = key; | |
config.sortOrder = order !== undefined ? order : 'desc'; | |
} | |
console.log(elem.parentNode); | |
elem.parentNode.classList.add(sortClass,sortedDirClass()); | |
renderPages(); | |
} | |
</script> | |
<div class="metricsBody slds-scope"> | |
<apex:sectionHeader title="VisualForce Page Metrics" | |
description="This page displays your organization's VisualForce page usage, by views." | |
help="https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_tools_metrics.htm"/> | |
<div id="formData" style="display:none;"> | |
<div class="slds-grid"> | |
<div class="slds-col"> | |
<div data-reactroot="" class="slds-form slds-form_stacked slds-m-bottom_medium"> | |
<div data-reactroot="" class="slds-form-element"> | |
<label class="slds-form-element__label" for="filterSince">Metrics Since: </label> | |
<div class="slds-form-element__control"> | |
<div class="slds-select_container slds-size_small"> | |
<select class="slds-select" id="filterSince"> | |
<option value="YESTERDAY">Yesterday</option> | |
<option value="LAST_WEEK">Last Week</option> | |
<option value="LAST_MONTH">Last Month</option> | |
<option value="LAST_YEAR">Last Year</option> | |
<option value="">All Time</option> | |
</select> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<table id="dataTable" data-reactroot="" class="slds-table slds-table_bordered slds-table_resizable-cols slds-table_fixed-layout" role="grid"> | |
<thead> | |
<tr class="slds-text-title_caps slds-line-height_reset"> | |
<th class="slds-is-sortable slds-text-title_caps" scope="col" id="filter_Name"> | |
<a href="javascript:void(0);" onclick="sortBy(this,'Name')" class="slds-th__action slds-text-link_reset" tabindex="0"> | |
<span class="slds-assistive-text">Sort </span> | |
<span class="slds-truncate" title="Name">Name</span> | |
<div class="slds-icon_container"> | |
<svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true"> | |
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS,'assets/icons/utility-sprite/svg/symbols.svg#arrowdown')}"></use> | |
</svg> | |
</div> | |
<span class="slds-assistive-text" aria-live="assertive" aria-atomic="true"></span> | |
</a> | |
</th> | |
<th class="slds-is-sortable slds-text-title_caps slds-is-sorted slds-is-sorted_desc" scope="col" id="filter_Views"> | |
<a href="javascript:void(0);" onclick="sortBy(this,'Views')" class="slds-th__action slds-text-link_reset" tabindex="0"> | |
<span class="slds-assistive-text">Sort </span> | |
<span class="slds-truncate" title="Views">Views</span> | |
<div class="slds-icon_container"> | |
<svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true"> | |
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS,'assets/icons/utility-sprite/svg/symbols.svg#arrowdown')}"></use> | |
</svg> | |
</div> | |
<span class="slds-assistive-text" aria-live="assertive" aria-atomic="true"></span> | |
</a> | |
</th> | |
<th class="slds-is-sortable slds-text-title_caps" scope="col" id="filter_CreatedDate"> | |
<a href="javascript:void(0);" onclick="sortBy(this,'CreatedDate');" class="slds-th__action slds-text-link_reset" tabindex="0"> | |
<span class="slds-assistive-text">Sort </span> | |
<span class="slds-truncate" title="Created Date">Created Date</span> | |
<div class="slds-icon_container"> | |
<svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true"> | |
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS,'assets/icons/utility-sprite/svg/symbols.svg#arrowdown')}"></use> | |
</svg> | |
</div> | |
<span class="slds-assistive-text" aria-live="assertive" aria-atomic="true"></span> | |
</a> | |
</th> | |
<th class="slds-is-sortable slds-text-title_caps" scope="col" id="filter_LastModifiedDate"> | |
<a href="javascript:void(0);" onclick="sortBy(this, 'LastModifiedDate');" class="slds-th__action slds-text-link_reset" tabindex="0"> | |
<span class="slds-assistive-text">Sort </span> | |
<span class="slds-truncate" title="Created Date">Last Modified Date</span> | |
<div class="slds-icon_container"> | |
<svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true"> | |
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS,'assets/icons/utility-sprite/svg/symbols.svg#arrowdown')}"></use> | |
</svg> | |
</div> | |
<span class="slds-assistive-text" aria-live="assertive" aria-atomic="true"></span> | |
</a> | |
</th> | |
<th class="slds-is-sortable slds-text-title_caps" scope="col" id="filter_LastModifiedBy"> | |
<a href="javascript:void(0);" onclick="sortBy(this, 'LastModifiedBy');" class="slds-th__action slds-text-link_reset" tabindex="0"> | |
<span class="slds-assistive-text">Sort </span> | |
<span class="slds-truncate" title="Created Date">Last Modified By</span> | |
<div class="slds-icon_container"> | |
<svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true"> | |
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{!URLFOR($Asset.SLDS,'assets/icons/utility-sprite/svg/symbols.svg#arrowdown')}"></use> | |
</svg> | |
</div> | |
<span class="slds-assistive-text" aria-live="assertive" aria-atomic="true"></span> | |
</a> | |
</th> | |
</tr> | |
</thead> | |
<tbody id="output"> | |
</tbody> | |
</table> | |
</div> | |
</div> | |
<apex:outputPanel rendered="{!$User.UIThemeDisplayed == 'Theme4d' || $User.UIThemeDisplayed == 'Theme4u' }" > | |
<style id="{!$User.UIThemeDisplayed}"> | |
.metricsBody { | |
padding: 1em 2em; | |
} | |
body .bDescription, body .bPageTitle{ | |
margin-bottom:1em; | |
} | |
body .bPageTitle .pageType{ | |
font-size: 2rem; | |
} | |
</style> | |
</apex:outputPanel> | |
</apex:page> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment