/*
|
* Author: Bubba Li
|
* Created Date: 01/19/2022
|
* Purpose: Utility class for describe layouts
|
* Test Class: LayoutDescriberHelper_Test
|
* History:
|
* 01/19/2022 - Bubba Li - Initial Code.
|
*
|
* */
|
|
public class LayoutDescriberHelper {
|
public static String urlPrefixToUse {get;set;}
|
public static Set<String> ConcatenationNameSType = new Set<String>{'Lead','Contact'};
|
public static List<LayoutSection> describeSectionWithFields(Id recordTypeId, String objectType,String userMode){
|
system.debug('record type id ===>'+ recordTypeId+' object type===>'+objectType + ' userMode===>'+userMode);
|
List<LayoutSection> layoutSections;
|
Map<String,List<LayoutField>> layoutFields;
|
layoutSections = new List<LayoutSection>();
|
String theRespBody = getLayoutSchema(recordTypeId, objectType,userMode);
|
Map<String, Object> layoutSection = (Map<String, Object>) JSON.deserializeUntyped(theRespBody);
|
Map<String,object> m = new Map<String,object>();
|
if(String.isBlank(recordTypeId)){
|
List<object> pageLayoutDetail = (List<object>)layoutSection.get('layouts');
|
System.debug('Page Layout Section Detail:'+JSON.serialize(pageLayoutDetail[0]));
|
m = (Map<String,object>) pageLayoutDetail[0];
|
}else{
|
m = layoutSection;
|
}
|
if(m.containsKey('editLayoutSections')){
|
List<object > targetLayout = (List<object>) m.get('editLayoutSections');
|
for(object sectionObject: targetLayout){
|
Map<String,object> section = (Map<String,object>) sectionObject;
|
String sectionH = (String)section.get('heading');
|
boolean useH = (boolean)section.get('useHeading');
|
integer columns = (integer)section.get('columns');
|
boolean useCollapse = (boolean)section.get('useCollapsibleSection');
|
LayoutSection ls = new LayoutSection();
|
ls.Name = sectionH;
|
ls.useHeader = useH;
|
ls.columns = columns;
|
ls.allowCollapse = useCollapse;
|
ls.layoutFields = new List<LayoutField>();
|
layoutSections.add(ls);
|
List<object> layoutRows = (List<object>) section.get('layoutRows');
|
system.debug('layout rows ====> '+layoutRows);
|
for(Object itemObject : layoutRows ){
|
Map<String,object> item = (Map<String,object>) itemObject;
|
List<object> layoutItem = (List<object>)item.get('layoutItems');
|
boolean priorFieldLayoutAdded = true;//initially true
|
for(object fieldItemObject : layoutItem){
|
Map<String, object> fields = (Map<String,object>) fieldItemObject;
|
List<object> layoutComponents = (List<object>) fields.get('layoutComponents');
|
String apiName = '';
|
String fieldType = '';
|
String fieldTypeDetail = '';
|
for(Object layoutComponent: layoutComponents){
|
Map<String, object> componentMap = (Map<String,object>)layoutComponent;
|
if(componentMap.containsKey('value')){
|
apiName = (String) componentMap.get('value');
|
}
|
|
if(componentMap.containsKey('type')){
|
fieldType = (String) componentMap.get('type');
|
}
|
|
if(componentMap.containsKey('details')){
|
Map<String,object> detailsMap = (Map<String,object>) componentMap.get('details');
|
boolean calculatedField = (boolean)detailsMap.get('calculated');
|
boolean autoNumberField = (boolean)detailsMap.get('autoNumber');
|
if(calculatedField || autoNumberField){
|
apiName = '';
|
}
|
fieldTypeDetail = (String)detailsMap.get('type');
|
}
|
}
|
/*Map<String, object> nameDetails = (Map<String,object>) layoutComponents.get('Name');*/
|
String fieldLabel = (String) fields.get('label');
|
boolean placeholderF = (boolean) fields.get('placeholder');
|
boolean isEditable = (boolean) fields.get('editableForNew'); // Check the editable prop
|
if( (apiName != '' && fieldType =='Field') || (placeholderF)){
|
if(userMode == 'classic' && fieldTypeDetail == 'address'){
|
String fieldLabelPrefix = fieldLabel.split(' ')[0] == 'Address'?'':fieldLabel.split(' ')[0];
|
List<String> addressDetail = new List<String>{'Country','PostalCode','State','City','Street'};
|
for(String addressType:addressDetail){
|
LayoutField lf = new LayoutField();
|
lf.isRequired = (Boolean)fields.get('required');
|
lf.isPlaceHolder = placeholderF;
|
lf.editableField = isEditable;
|
lf.fieldAPI = fieldLabelPrefix+addressType;
|
lf.fieldLabel = fieldLabelPrefix+' '+addressType;
|
lf.fieldType = 'string';
|
if(ls.Name != '' || layoutSections.size() == 1){
|
ls.layoutFields.add(lf);
|
}else if(layoutSections.size() - 2 >= 0){
|
layoutSections.get(layoutSections.size() - 2).layoutFields.add(lf);
|
}
|
}
|
continue;
|
}
|
if(userMode == 'classic' && apiName == 'Name' && ConcatenationNameSType.contains(objectType)){
|
List<String> nameDetail = new List<String>{'LastName'};
|
for(String nameField:nameDetail){
|
LayoutField lf = new LayoutField();
|
lf.isRequired = (Boolean)fields.get('required');
|
lf.isPlaceHolder = placeholderF;
|
lf.editableField = isEditable;
|
lf.fieldAPI = nameField;
|
lf.fieldLabel = nameField;
|
lf.fieldType = 'string';
|
if(ls.Name != '' || layoutSections.size() == 1){
|
ls.layoutFields.add(lf);
|
}else if(layoutSections.size() - 2 >= 0){
|
layoutSections.get(layoutSections.size() - 2).layoutFields.add(lf);
|
}
|
}
|
continue;
|
}
|
LayoutField lf = new LayoutField();
|
lf.isRequired = (Boolean)fields.get('required');
|
lf.isPlaceHolder = placeholderF;
|
lf.editableField = isEditable;
|
lf.fieldAPI = apiName;
|
lf.fieldLabel = fieldLabel;
|
lf.fieldType = fieldTypeDetail;
|
if(ls.Name != '' || layoutSections.size() == 1){
|
ls.layoutFields.add(lf);
|
}else if(layoutSections.size() - 2 >= 0){
|
layoutSections.get(layoutSections.size() - 2).layoutFields.add(lf);
|
}
|
priorFieldLayoutAdded = true;
|
}else
|
priorFieldLayoutAdded = false;
|
}
|
}
|
if(layoutSections.get(layoutSections.size() -1).layoutFields.size() <= 0) {
|
layoutSections.remove(layoutSections.size() - 1);
|
}
|
}
|
}
|
System.debug('Layout Section Result:'+JSon.serialize(layoutSections));
|
return layoutSections;
|
}
|
public static String getUrlPrefix(){
|
String baseurl= System.URL.getOrgDomainUrl().getHost();
|
system.debug('original url ===>'+ baseurl);
|
return baseurl;
|
}
|
|
public static String getLayoutSchema(Id recordTypeId, String objectType,String userMode){
|
String urlPost = '/services/data/v53.0/sobjects/'+objectType+'/describe/layouts/';
|
if(String.isNotEmpty(recordTypeId) && String.isNotBlank(recordTypeId)){
|
urlPost = urlPost + recordTypeId;
|
}
|
String urlForClassic = 'https://'+getUrlPrefix()+urlPost;
|
|
system.debug('URL Post:'+urlForClassic);
|
HttpResponse resp = null;
|
HttpRequest req = new HttpRequest();
|
req.setMethod('GET');
|
if(userMode =='lightning'){
|
req.setEndPoint('callout:SF_Rest_API'+urlPost);
|
}else if(userMode == 'classic'){
|
req.setEndpoint(urlForClassic);
|
req.setHeader('Authorization', 'Bearer ' + UserInfo.getsessionid());
|
}
|
Http client = new Http();
|
resp = client.send(req);
|
system.debug('Schema Body:'+JSON.serialize(resp.getBody()));
|
return resp.getBody();
|
}
|
|
public static Id getDefaultRecordType(SObject obj) {
|
Schema.DescribeSObjectResult describeResult = obj.getsObjectType().getDescribe();
|
List<Schema.RecordTypeInfo> rtInfos = describeResult.getRecordTypeInfos();
|
for(Schema.RecordTypeInfo rtInfo : rtInfos) {
|
if(rtInfo.DefaultRecordTypeMapping) {
|
return rtInfo.getRecordTypeId();
|
}
|
}
|
return null;
|
}
|
|
public class LayoutSection{
|
@AuraEnabled public boolean useHeader {get;set;}
|
@AuraEnabled public String name {get;set;}
|
@AuraEnabled public boolean allowCollapse {get;set;}
|
@AuraEnabled public integer columns {get;set;}
|
@AuraEnabled public List<LayoutField> layoutFields {get;set;}
|
}
|
|
public class LayoutField{
|
@AuraEnabled public String fieldAPI {get;set;}
|
@AuraEnabled public String fieldLabel{set;get;}
|
@AuraEnabled public String fieldType{set;get;}
|
@AuraEnabled public boolean editableField {get;set;}
|
@AuraEnabled public boolean isRequired {get; set;}
|
@AuraEnabled public boolean isPlaceHolder {get;set;}
|
@AuraEnabled public String defaultValue{set;get;}
|
}
|
}
|