5

This question has been asked by few previously and i see the answers are not pointing to the correct scenario

I am having a need to deploy a new lightning home page and set it as default for the complete org across apps or profiles. In the UI i am able to do it with the 'Set Default Home Page' screen as below. You can see there are two home pages and i choose one, but i am not able to do this action via metadata api deployment. I see we have profileActionOverrides option which is set at app level but i have many apps and this needs to be set org wide and not at app level.

So is there a metadata tag i am missing which can set a new homepage as default or should i use profileActionOverrides and set the override in each app (have around 40 apps, which is a lot of workaround for a simple org default 😕)

enter image description here

2 Answers 2

1

enter image description here If I understand your question right, all these configurations must end up with the same new Lightning Page (FlexiPage), so let's start.

  • Preparations: Create MetadataService class with Setup -> API -> Metadata WSDL. Setup -> Apex Classes -> Generate from WSDL. (Or just get it from git).
  • Prepare your MetadataPort:
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
service.SessionHeader = new MetadataService.SessionHeader_element();
service.SessionHeader.sessionId = UserInfo.getSessionId();
service.CallOptions = new MetadataService.CallOptions_element();
service.timeout_x = 120000;
  • Set up your newLightningPageName:
String newLightningPageName = 'ORGDEF';
  • Read standard home page (Default Home Page in the picture):
MetadataService.CustomTab standardHomeTabForAllApps = ((List <MetadataService.CustomTab>) service.readMetadata('CustomTab', new List<String>{'standard-home'}).getRecords())[0];
  • Replace or add action override for custom tab with new lighting page:
Boolean replaced = false;

for (MetadataService.ActionOverride action : standardHomeTabForAllApps.actionOverrides) {
    if (action.actionName == 'Tab' && action.type_x == 'FlexiPage') {
        action.content = newLightningPageName;
        replaced = true;
        break;
    }
}

if (!replaced) {
    MetadataService.ActionOverride newAction = new MetadataService.ActionOverride();
    newAction.actionName = 'Tab';
    newAction.type_x = 'FlexiPage';
    newAction.content = newLightningPageName;
    if (standardHomeTabForAllApps.actionOverrides == null) {
        standardHomeTabForAllApps.actionOverrides = new List<MetadataService.ActionOverride>();
    }
    standardHomeTabForAllApps.actionOverrides.add(newAction);
}
  • Update metadata:
service.updateMetadata(new List<MetadataService.CustomTab>{standardHomeTabForAllApps});
  • Retrieve all your applications names:
MetadataService.ListMetadataQuery query = new MetadataService.ListMetadataQuery();
query.type_x = 'CustomApplication';

List<MetadataService.FileProperties> applications = service.listMetadata(new List<MetadataService.ListMetadataQuery>{query}, 53);

List<String> applicationsNames = new List<String>();
for (MetadataService.FileProperties application : applications) {
    if (String.isNotBlank(application.fullName)) {
        applicationsNames.add(application.fullName);
    }
}
  • Read your applications metadata:
List<MetadataService.CustomApplication> applicationsMetadata = (List <MetadataService.CustomApplication>) service.readMetadata('CustomApplication', applicationsNames).getRecords();
  • Replace action override (only replace without adding, because org default home page is already set up):
List<MetadataService.CustomApplication> applicationsMetadataToUpdate = new List<MetadataService.CustomApplication>();
for (MetadataService.CustomApplication applicationMetadata : applicationsMetadata) {
    if (applicationMetadata.uiType == 'Lightning') { //works for lightning apps only
        if (applicationMetadata.actionOverrides != null) {
            for (MetadataService.AppActionOverride action : applicationMetadata.actionOverrides) { //Assignments by App
                if (action.pageOrSobjectType == 'standard-home' && action.actionName == 'Tab' && action.type_x == 'FlexiPage') {
                    action.content = newLightningPageName;
                }
            }
        }
        
        if (applicationMetadata.profileActionOverrides != null) {
            for (MetadataService.AppProfileActionOverride action : applicationMetadata.profileActionOverrides) { //Assignments by App and Profile
                if (action.pageOrSobjectType == 'standard-home' && action.actionName == 'Tab' && action.type_x == 'FlexiPage') {
                    action.content = newLightningPageName;
                }
            }
        }

        applicationsMetadataToUpdate.add(applicationMetadata);
    }
}
  • Update metadata:
Integer MAX_BATCH_METADATA_SIZE = 10;
List<MetadataService.CustomApplication> batch = new List<MetadataService.CustomApplication>();
for (MetadataService.CustomApplication application : applicationsMetadataToUpdate) {
    batch.add(application);
    if (batch.size() == MetadataHelper.MAX_BATCH_METADATA_SIZE) {
        service.updateMetadata(batch);
        batch.clear();
    }
}

if (batch.size() > 0) {
    service.updateMetadata(batch);
}

Important note: if you are going to use MetadataService from git, you will need to update several classes like this:

public virtual class GlobalActionOverride extends Metadata {
    public String fullName;
    public String actionName;
    public String comment;
    public String content;
    public String formFactor;
    public Boolean skipRecordTypeSelect;
    public String type_x;
    private String[] fullName_type_info = new String[]{'fullName',SOAP_M_URI,null,'0','1','false'};
    private String[] actionName_type_info = new String[]{'actionName',SOAP_M_URI,null,'0','1','false'};
    private String[] comment_type_info = new String[]{'comment',SOAP_M_URI,null,'0','1','false'};
    private String[] content_type_info = new String[]{'content',SOAP_M_URI,null,'0','1','false'};
    private String[] formFactor_type_info = new String[]{'formFactor',SOAP_M_URI,null,'0','1','false'};
    private String[] skipRecordTypeSelect_type_info = new String[]{'skipRecordTypeSelect',SOAP_M_URI,null,'0','1','false'};
    private String[] type_x_type_info = new String[]{'type',SOAP_M_URI,null,'0','1','false'};
    private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'};
    private String[] field_order_type_info = new String[]{'fullName','actionName','comment','content','formFactor','skipRecordTypeSelect','type_x'};
}
public class AppActionOverride extends GlobalActionOverride {
    public String type = 'AppActionOverride';
    public String fullName;
    private String[] fullName_type_info = new String[]{'fullName',SOAP_M_URI,null,'0','1','false'};
    public String actionName;
    public String comment;
    public String content;
    public String formFactor;
    public Boolean skipRecordTypeSelect;
    public String pageOrSobjectType;
    public String type_x;
    private String[] actionName_type_info = new String[]{'actionName',SOAP_M_URI,null,'0','1','false'};
    private String[] comment_type_info = new String[]{'comment',SOAP_M_URI,null,'0','1','false'};
    private String[] content_type_info = new String[]{'content',SOAP_M_URI,null,'0','1','false'};
    private String[] formFactor_type_info = new String[]{'formFactor',SOAP_M_URI,null,'0','1','false'};
    private String[] skipRecordTypeSelect_type_info = new String[]{'skipRecordTypeSelect',SOAP_M_URI,null,'0','1','false'};
    private String[] type_x_type_info = new String[]{'type',SOAP_M_URI,null,'0','1','false'};
    private String[] pageOrSobjectType_type_info = new String[]{'pageOrSobjectType',SOAP_M_URI,null,'1','1','false'};
    private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'};
    private String[] type_att_info = new String[]{'xsi:type'};
    private String[] field_order_type_info = new String[]{'fullName','actionName','comment','content','formFactor','skipRecordTypeSelect','type_x','pageOrSobjectType'};
}
public class AppProfileActionOverride extends GlobalActionOverride {
    public String type = 'AppProfileActionOverride';
    public String fullName;
    private String[] fullName_type_info = new String[]{'fullName',SOAP_M_URI,null,'0','1','false'};
    public String actionName;
    public String comment;
    public String content;
    public String formFactor;
    public Boolean skipRecordTypeSelect;
    public String type_x;
    public String pageOrSobjectType;
    public String profile;
    private String[] actionName_type_info = new String[]{'actionName',SOAP_M_URI,null,'0','1','false'};
    private String[] comment_type_info = new String[]{'comment',SOAP_M_URI,null,'0','1','false'};
    private String[] content_type_info = new String[]{'content',SOAP_M_URI,null,'0','1','false'};
    private String[] formFactor_type_info = new String[]{'formFactor',SOAP_M_URI,null,'0','1','false'};
    private String[] skipRecordTypeSelect_type_info = new String[]{'skipRecordTypeSelect',SOAP_M_URI,null,'0','1','false'};
    private String[] type_x_type_info = new String[]{'type',SOAP_M_URI,null,'0','1','false'};
    private String[] pageOrSobjectType_type_info = new String[]{'pageOrSobjectType',SOAP_M_URI,null,'1','1','false'};
    private String[] profile_type_info = new String[]{'profile',SOAP_M_URI,null,'1','1','false'};
    private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'};
    private String[] type_att_info = new String[]{'xsi:type'};
    private String[] field_order_type_info = new String[]{'fullName','actionName','comment','content','formFactor','skipRecordTypeSelect','type_x','pageOrSobjectType','profile'};
}
public class ReadGlobalActionOverrideResult implements IReadResult {
    public MetadataService.GlobalActionOverride[] records;
    public MetadataService.Metadata[] getRecords() { return records; }
    private String[] records_type_info = new String[]{'records',SOAP_M_URI,null,'0','-1','false'};
    private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'};
    private String[] field_order_type_info = new String[]{'records'};
}
public class readGlobalActionOverrideResponse_element implements IReadResponseElement {
    public MetadataService.ReadGlobalActionOverrideResult result;
    public IReadResult getResult() { return result; }
    private String[] result_type_info = new String[]{'result',SOAP_M_URI,null,'1','1','false'};
    private String[] apex_schema_type_info = new String[]{SOAP_M_URI,'true','false'};
    private String[] field_order_type_info = new String[]{'result'};
}
2
  • Does it set homepage on organization level or for every app? If it's the latter then it's not an answer to the question I believe. Also you should provide more details on what to do with apex code. Commented Feb 17, 2022 at 7:21
  • @user2475983 I have updated my answer. Commented Feb 17, 2022 at 10:08
0

Try the metadata in the Custom object itself, it should look like this:

<actionOverrides>
 <actionName>View</actionName>
 <comment>Action override created by Lightning App Builder during activation.</comment>
 <content>[Record Pages Name]</content>
 <formFactor>Large</formFactor>
 <skipRecordTypeSelect>false</skipRecordTypeSelect>
 <type>Flexipage</type>
</actionOverrides>
1
  • 1
    It's for sobject record page, but the question is referring to home page. Commented Feb 16, 2022 at 13:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .