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. Feb 17, 2022 at 7:21
  • @user2475983 I have updated my answer. 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. Feb 16, 2022 at 13:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.