diff --git a/IlluminatedCloud/Salesforce_Indicators__dev/OfflineSymbolTable.zip b/IlluminatedCloud/Salesforce_Indicators__dev/OfflineSymbolTable.zip new file mode 100644 index 0000000..ca3c7ab Binary files /dev/null and b/IlluminatedCloud/Salesforce_Indicators__dev/OfflineSymbolTable.zip differ diff --git a/force-app/main/default/classes/Cmdt.cls b/force-app/main/default/classes/Cmdt.cls index b36d92c..c8122a9 100644 --- a/force-app/main/default/classes/Cmdt.cls +++ b/force-app/main/default/classes/Cmdt.cls @@ -5,19 +5,19 @@ public with sharing class Cmdt { // Gather all active Bundles and put them into a Map (key: DeveloperName; Bundle) for( Indicator_Bundle__mdt bundle : [ - SELECT Id, DeveloperName, MasterLabel, Label, - Active__c, - Card_Icon__c, - Card_Icon_Background__c, - Card_Icon_Foreground__c, - Card_Text__c, - Card_Title__c, - Description__c, - sObject__c, - sObject__r.QualifiedApiName, - sObject__r.Label - FROM Indicator_Bundle__mdt - ORDER BY Label + SELECT Id, DeveloperName, MasterLabel, Label, QualifiedApiName, + Active__c, + Card_Icon__c, + Card_Icon_Background__c, + Card_Icon_Foreground__c, + Card_Text__c, + Card_Title__c, + Description__c, + sObject__c, + sObject__r.QualifiedApiName, + sObject__r.Label + FROM Indicator_Bundle__mdt + WHERE Delete__c != TRUE ] ) { setBundle(bundle); } @@ -25,31 +25,32 @@ public with sharing class Cmdt { // Gather all active Items and put them into a Map (key: Developername; Item) // Using SOQL because of parent-related values AND Advanced_Field__c is long text. for( Indicator_Item__mdt item : [ - SELECT Id, DeveloperName, MasterLabel, - Active__c, - Advanced_Field__c, - Advanced_Field_Label__c, - Display_Multiple__c, - Empty_Static_Text_Behavior__c, - Field__c, Field__r.QualifiedApiName, - Hover_Text__c, - Icon_Value__c, - Image__c, - Inverse_Hover_Text__c, - Inverse_Icon_Value__c, - Inverse_Image__c, - Inverse_Static_Text__c, - Show_False_or_Blank__c, - sObject__c, sObject__r.QualifiedApiName, - Static_Text__c, - Zero_Behavior__c, - Icon_Background__c, - Icon_Foreground__c, - Inverse_Icon_Background__c, - Inverse_Icon_Foreground__c, - Description__c - FROM Indicator_Item__mdt - // WHERE Active__c = TRUE + SELECT Id, DeveloperName, MasterLabel, Label, QualifiedApiName, + Active__c, + Advanced_Field__c, + Advanced_Field_Label__c, + Display_Multiple__c, + Empty_Static_Text_Behavior__c, + Field__c, Field__r.QualifiedApiName, + Hover_Text__c, + Icon_Value__c, + Image__c, + Inverse_Hover_Text__c, + Inverse_Icon_Value__c, + Inverse_Image__c, + Inverse_Static_Text__c, + Show_False_or_Blank__c, + sObject__c, sObject__r.QualifiedApiName, + Static_Text__c, + Zero_Behavior__c, + Icon_Background__c, + Icon_Foreground__c, + Inverse_Icon_Background__c, + Inverse_Icon_Foreground__c, + Description__c + FROM Indicator_Item__mdt + WHERE Delete__c != TRUE + // WHERE Active__c = TRUE ]){ setItem(item); } @@ -57,13 +58,15 @@ public with sharing class Cmdt { // Gather all active Bundle Items (Bundle and Item are active) and put them into a Map (key: Bundle DeveloperName; List of BundleItems) // Using SOQL because of the Order By clause rather than creating a custom sort method. for( Indicator_Bundle_Item__mdt bundleItem : [ - SELECT Indicator_Bundle__c, Indicator_Bundle__r.DeveloperName, - Indicator_Item__c, Indicator_Item__r.DeveloperName, - Order__c - FROM Indicator_Bundle_Item__mdt - // WHERE Indicator_Bundle__r.Active__c = TRUE - // AND Indicator_Item__r.Active__c = TRUE - ORDER BY Order__c + SELECT Id, DeveloperName, QualifiedApiName, MasterLabel, Label, + Indicator_Bundle__c, Indicator_Bundle__r.DeveloperName, Indicator_Bundle__r.QualifiedApiName, + Indicator_Item__c, Indicator_Item__r.DeveloperName, Indicator_Item__r.QualifiedApiName, + Order__c + FROM Indicator_Bundle_Item__mdt + WHERE Delete__c != TRUE + // WHERE Indicator_Bundle__r.Active__c = TRUE + // AND Indicator_Item__r.Active__c = TRUE + ORDER BY Order__c ]){ setBundleItem(bundleItem); } @@ -71,25 +74,28 @@ public with sharing class Cmdt { // Gather all active Item Extensions and put them into a Map (key: Indicator Item; List of Extensions) // Using SOQL because of the Order By clause rather than creating a custom sort method. for(Indicator_Item_Extension__mdt itemExtension : [ - SELECT Id, Active__c, - Contains_Text__c, - Text_Operator__c, - Hover_Text__c, - Icon_Value__c, - Image__c, - Indicator_Item__c, - Indicator_Item__r.DeveloperName, - Maximum__c, - Minimum__c, - Priority__c, - Static_Text__c, - Icon_Background__c, - Icon_Foreground__c, - Description__c - FROM Indicator_Item_Extension__mdt - // WHERE Active__c = TRUE - // AND Indicator_Item__r.Active__c = TRUE - ORDER BY Indicator_Item__c, Priority__c DESC, MasterLabel + SELECT Id, DeveloperName, QualifiedApiName, Label, MasterLabel, + Active__c, + Contains_Text__c, + Text_Operator__c, + Hover_Text__c, + Icon_Value__c, + Image__c, + Indicator_Item__c, + Indicator_Item__r.DeveloperName, + Indicator_Item__r.QualifiedApiName, + Maximum__c, + Minimum__c, + Priority__c, + Static_Text__c, + Icon_Background__c, + Icon_Foreground__c, + Description__c + FROM Indicator_Item_Extension__mdt + WHERE Delete__c != TRUE + // WHERE Active__c = TRUE + // AND Indicator_Item__r.Active__c = TRUE + ORDER BY Indicator_Item__c, Priority__c DESC, MasterLabel ]){ setItemExtension(itemExtension); } @@ -144,7 +150,7 @@ public with sharing class Cmdt { } public static List getAllOrphanItems(){ - + List orphanItems = new List(); for(String itemName : itemsByName.keyset()){ @@ -160,28 +166,28 @@ public with sharing class Cmdt { if(bundlesByName.containsKey(bundleDevName)) return bundlesByName.get(bundleDevName); else - return new Indicator_Bundle__mdt(); + return new Indicator_Bundle__mdt(); } public static Indicator_Item__mdt getItem(String itemDevName){ if(itemsByName.containsKey(itemDevName)) return itemsByName.get(itemDevName); else - return new Indicator_Item__mdt(); + return new Indicator_Item__mdt(); } public static List getBundleItems(String bundleDevName){ if(bundleItemsByBundle.containsKey(bundleDevname)) return bundleItemsByBundle.get(bundleDevName); - else - return new List(); + else + return new List(); } public static List getExtensionsForItem(String itemDevName){ if(extensionsByItem.containsKey(itemDevName)) return extensionsByItem.get(itemDevName); else - return new List(); + return new List(); } // Static variables used across methods. diff --git a/force-app/main/default/classes/IndicatorController.cls b/force-app/main/default/classes/IndicatorController.cls index c2859c2..c39ab8f 100644 --- a/force-app/main/default/classes/IndicatorController.cls +++ b/force-app/main/default/classes/IndicatorController.cls @@ -343,4 +343,9 @@ public with sharing class IndicatorController { return wrapper; } + @AuraEnabled(Cacheable=true) + public static MetadataUtility.indicatorBundle getIndicatorBundleWrapper(String QualifiedApiName) { + return new MetadataUtility.indicatorBundle(QualifiedApiName); + } + } \ No newline at end of file diff --git a/force-app/main/default/classes/MetadataDeploy.cls b/force-app/main/default/classes/MetadataDeploy.cls new file mode 100644 index 0000000..105b2c4 --- /dev/null +++ b/force-app/main/default/classes/MetadataDeploy.cls @@ -0,0 +1,23 @@ +/** + * Created by robertwright on 10/30/23. + */ + +public with sharing class MetadataDeploy implements Metadata.DeployCallback { + + public String resultMessage; + + public void handleResult(Metadata.DeployResult result,Metadata.DeployCallbackContext context) { + if(result.status === Metadata.DeployStatus.Succeeded) { + resultMessage = 'MetaData Deploy Succeeded'; + } else resultMessage = 'MetaData Deploy Failed'; + if(Test.isRunningTest()) System.debug(resultMessage); + } + + public static Id upsertMetaData(Metadata.DeployContainer deployContainer) { + MetadataDeploy callback = new MetadataDeploy(); + Id upsertId; + if(!Test.isRunningTest()) upsertId = Metadata.Operations.enqueueDeployment(deployContainer,callback); + return upsertId; + } + +} \ No newline at end of file diff --git a/force-app/main/default/classes/MetadataDeploy.cls-meta.xml b/force-app/main/default/classes/MetadataDeploy.cls-meta.xml new file mode 100644 index 0000000..7a51829 --- /dev/null +++ b/force-app/main/default/classes/MetadataDeploy.cls-meta.xml @@ -0,0 +1,5 @@ + + + 58.0 + Active + diff --git a/force-app/main/default/classes/MetadataDeployTests.cls b/force-app/main/default/classes/MetadataDeployTests.cls new file mode 100644 index 0000000..1131fc6 --- /dev/null +++ b/force-app/main/default/classes/MetadataDeployTests.cls @@ -0,0 +1,10 @@ +/** + * Created by robertwright on 10/30/23. + */ + +@IsTest +private class MetadataDeployTests { + @IsTest + static void testBehavior() { + } +} \ No newline at end of file diff --git a/force-app/main/default/classes/MetadataDeployTests.cls-meta.xml b/force-app/main/default/classes/MetadataDeployTests.cls-meta.xml new file mode 100644 index 0000000..7a51829 --- /dev/null +++ b/force-app/main/default/classes/MetadataDeployTests.cls-meta.xml @@ -0,0 +1,5 @@ + + + 58.0 + Active + diff --git a/force-app/main/default/classes/MetadataUtility.cls b/force-app/main/default/classes/MetadataUtility.cls new file mode 100644 index 0000000..43d1954 --- /dev/null +++ b/force-app/main/default/classes/MetadataUtility.cls @@ -0,0 +1,261 @@ +/** + * Created by robertwright on 10/30/23. + */ + +public with sharing class MetadataUtility { + + /**Static Params**/ + private static final String Label_Field = 'Label'; + private static final String QualifiedApiName_Field = 'QualifiedApiName'; + private static final Set entityRelationshipFields = new Set{ + Indicator_Bundle__mdt.sObject__c.getDescribe(), + Indicator_Item__mdt.Field__c.getDescribe(), + Indicator_Item__mdt.sObject__c.getDescribe(), + Indicator_Item_Extension__mdt.Indicator_Item__c.getDescribe() + }; + + private static Metadata.DeployContainer deployContainer; + private static DescribeSObjectResult describeSObjectResult; + private static Map populatedFieldsMap; + + /**Wrappers**/ + public class deploymentWrapper { + @AuraEnabled public Indicator_Bundle__mdt indicatorBundle; + @AuraEnabled public List indicatorBundleItems; + @AuraEnabled public Indicator_Item__mdt indicatorItem; + @AuraEnabled public List indicatorItemExtensions; + + public deploymentWrapper() {} + } + + /**Controller Methods**/ + @AuraEnabled + public static Id deployIndicatorBundles(String wrapper) { + System.debug(wrapper); + + deploymentWrapper parsedWrapper = (MetadataUtility.deploymentWrapper) JSON.deserialize(wrapper,MetadataUtility.deploymentWrapper.class); + + System.debug(parsedWrapper); + + return deployWrapperMetadata(parsedWrapper); + } + + /**Metadata Methods**/ + private static Id deployWrapperMetadata(deploymentWrapper wrapper) { + System.debug(wrapper); + deployContainer = new Metadata.DeployContainer(); // Build New Deployment Container + if(wrapper.indicatorBundle != null) processMetadataRecords(new List{wrapper.indicatorBundle},Indicator_Bundle__mdt.getSObjectType()); + if(wrapper.indicatorItem != null) processMetadataRecords(new List{wrapper.indicatorItem},Indicator_Item__mdt.getSObjectType()); + if(wrapper.indicatorItemExtensions != null && !wrapper.indicatorItemExtensions.isEmpty()) processMetadataRecords(wrapper.indicatorItemExtensions,Indicator_Item_Extension__mdt.getSObjectType()); + if(wrapper.indicatorBundleItems != null && !wrapper.indicatorBundleItems.isEmpty()) processMetadataRecords(wrapper.indicatorBundleItems,Indicator_Bundle_Item__mdt.getSObjectType()); + Id deployId = MetadataDeploy.upsertMetaData(deployContainer); // Deploy Deploy Container + return deployId; + } + + private static void processMetadataRecords(List records,SObjectType sObjectType) { + System.debug(records); + describeSObjectResult = sObjectType.getDescribe(); + for(SObject record : records) buildMetaData(record.getPopulatedFieldsAsMap()); // Build Metadata Maps and Add to Deploy Container + } + + private static void buildMetaData(Map metadataFieldValueMap) { + populatedFieldsMap = metadataFieldValueMap; + if(populatedFieldsMap == null) populatedFieldsMap = new Map(); + + String sObjectName = describeSObjectResult.getName(); + String QualifiedApiName = (String) populatedFieldsMap.get(QualifiedApiName_Field); + String fullName = mergeFullName(sObjectName,QualifiedApiName); + String label = (String) populatedFieldsMap.get(Label_Field); + + if(String.isBlank(label)) label = 'Unnamed Metadata'; + + System.debug(fullName+' '+label); + + Metadata.CustomMetadata customMetadata = buildCustomMetadata(fullName,label); + deployContainer.addMetadata(customMetadata); + } + + private static String mergeFullName(String metadataName, String QualifiedApiName) { + String DeveloperName = (QualifiedApiName.length() > 40) ? QualifiedApiName.substring(0,40) : QualifiedApiName; + return metadataName.replace('__mdt','')+'.'+DeveloperName; + } + + private static Metadata.CustomMetadata buildCustomMetadata(String fullName, String recordLabel) { + Metadata.CustomMetadata customMetadata = new Metadata.CustomMetadata(); + customMetadata.fullName = fullName; + customMetadata.label = (recordLabel.length() > 40) ? recordLabel.substring(0,40) : recordLabel; + + Map describeFieldMap = describeSObjectResult.fields.getMap(); + + for(String fieldName : populatedFieldsMap.keySet()) processCustomMetadataFieldValues(customMetadata,describeFieldMap.get(fieldName)); + + return customMetadata; + } + + private static void processCustomMetadataFieldValues(Metadata.CustomMetadata customMetadata,Schema.SObjectField sObjectField) { + if(sObjectField == null) return; /**Return if sObjectField not found**/ + DescribeFieldResult fieldResult = sObjectField.getDescribe(); + if(!fieldResult.isCustom()) return; /**Return If Standard Field**/ + + String fieldName = fieldResult.getName(); + Boolean isReference = fieldResult.getType() === DisplayType.REFERENCE; + Boolean isEntityRelationshipField = entityRelationshipFields.contains(fieldResult); + + Object value = null; + + if(isReference || isEntityRelationshipField) { + if(isEntityRelationshipField) { + Object rawValue = populatedFieldsMap.get(fieldName); + value = rawValue != null ? String.valueOf(rawValue) : null; + } else { + SObject relatedRecord; + Map relatedRecordPopulatedFieldMap; + String relationshipName = fieldResult.getRelationshipName(); + if(populatedFieldsMap.containsKey(relationshipName)) { + try{ + relatedRecord = (SObject) populatedFieldsMap.get(relationshipName); + relatedRecordPopulatedFieldMap = relatedRecord.getPopulatedFieldsAsMap(); + } catch(Exception ex) { + System.debug(ex.getMessage()); + } + } + if(relatedRecordPopulatedFieldMap != null && relatedRecordPopulatedFieldMap.containsKey('QualifiedApiName')) { + value = (String) relatedRecordPopulatedFieldMap.get('QualifiedApiName'); + } + } + } else if(populatedFieldsMap.containsKey(fieldName)) { + value = populatedFieldsMap.get(fieldName); + } + if(value == null || value == '' && fieldResult.defaultValue != null) value = fieldResult.defaultValue; + else if(value == null || value == '' && fieldResult.defaultValueFormula != null) value = fieldResult.defaultValueFormula.removeEnd('\'').removeEnd('"').removeStart('\'').removeStart('"'); + + Metadata.CustomMetadataValue metadataField = new Metadata.CustomMetadataValue(); + metadataField.field = fieldName; + metadataField.value = value; + + System.debug(fieldName+' : '+value); + + customMetadata.values.add(metadataField); + } + + + private static Set getCustomFields(SObjectType SObjectType) { + Set returnSet = new Set(); + if(SObjectType == null) return returnSet; /**Error No Matching Object**/ + Schema.DescribeSObjectResult objResult = SObjectType.getDescribe(); + for(SObjectField objectField : objResult.fields.getMap().values()) { + DescribeFieldResult fieldResult = objectField.getDescribe(); + if(fieldResult.isCustom()) returnSet.add(fieldResult.getName()); + } + return returnSet; + } + + private static final SObjectField indicatorBundleItem_Field_Order = Indicator_Bundle_Item__mdt.Order__c; + private static final SObjectField indicatorBundleItem_Field_Item = Indicator_Bundle_Item__mdt.Indicator_Item__c; + private static final SObjectField indicatorItemExtension_Field_Item = Indicator_Item_Extension__mdt.Indicator_Item__c; + + private static final SObjectField indicatorBundleItem_Field_Delete = Indicator_Bundle_Item__mdt.Delete__c; + private static final SObjectField indicatorItemExtension_Field_Delete = Indicator_Item_Extension__mdt.Delete__c; + private static final SObjectField indicatorItemExtension_Field_Priority = Indicator_Item_Extension__mdt.Priority__c; + private static final SObjectField indicatorItemExtension_Field_Indicator_Item = Indicator_Item_Extension__mdt.Indicator_Item__c; + + private static final SObjectField indicatorItem_Field_Delete = Indicator_Item__mdt.Delete__c; + private static final SObjectField indicatorItem_Field_sObject = Indicator_Item__mdt.sObject__c; + private static final SObjectField indicatorItem_Field_Field = Indicator_Item__mdt.Field__c; + + private static final Schema.ChildRelationship bundleItemRelationShip = Indicator_Bundle__mdt.SObjectType.getDescribe().getChildRelationships()[0]; + private static Schema.ChildRelationship getItemExtensionRelationShip() { + for(Schema.ChildRelationship relationship : Indicator_Item__mdt.SObjectType.getDescribe().getChildRelationships()) { + if(relationship.getField() == indicatorItemExtension_Field_Indicator_Item) return relationship; + } + return null; + } + + private static Indicator_Bundle__mdt getIndicatorBundle(String qualifiedApiName) { + Set indicatorBundleFields = new Set(getCustomFields(Indicator_Bundle__mdt.SObjectType)); + indicatorBundleFields.addAll(new Set{ + 'Id', + 'QualifiedApiName', + 'Label' + }); + + Set indicatorBundleItemFields = new Set(getCustomFields(Indicator_Bundle_Item__mdt.SObjectType)); + indicatorBundleItemFields.addAll(new Set{ + 'Id', + 'QualifiedApiName', + 'Label', + indicatorBundleItem_Field_Item.getDescribe().getRelationshipName()+'.QualifiedApiName' + }); + + String queryString = 'SELECT '; + queryString += String.join(new List(indicatorBundleFields),','); + + queryString += ',\n(SELECT '; + queryString += String.join(new List(indicatorBundleItemFields),',') +' \nFROM '+bundleItemRelationShip.getRelationshipName(); + queryString += ' \nWHERE '+indicatorBundleItem_Field_Delete.getDescribe().getName()+' != TRUE'; + queryString += ' \nORDER BY '+indicatorBundleItem_Field_Order.getDescribe().getName()+' ASC NULLS LAST)'; + + queryString += ' \nFROM '+Indicator_Bundle__mdt.SObjectType.getDescribe().getName(); + queryString += ' \nWHERE QualifiedApiName = :qualifiedApiName'; + + Map queryBindMap = new Map{ + 'qualifiedApiName' => qualifiedApiName + }; + + AccessLevel level = (Test.isRunningTest()) ? AccessLevel.SYSTEM_MODE : AccessLevel.USER_MODE; /**For Testing only we allow all fields**/ + List bundles = Database.queryWithBinds(queryString,queryBindMap,level); + + if(bundles.isEmpty()) return null; + else return bundles[0]; + } + private static List getAllIndicatorItems(String sObjectName) { + Set indicatorItemsFields = new Set(getCustomFields(Indicator_Item__mdt.SObjectType)); + indicatorItemsFields.addAll(new Set{ + 'Id', + 'QualifiedApiName', + 'Label', + indicatorItem_Field_Field.getDescribe().getName().replace('__c','__r')+'.QualifiedApiName' + }); + + Set indicatorItemExtensionFields = new Set(getCustomFields(Indicator_Item_Extension__mdt.SObjectType)); + indicatorItemExtensionFields.addAll(new Set{ + 'Id', + 'QualifiedApiName', + 'Label', + indicatorItemExtension_Field_Item.getDescribe().getRelationshipName()+'.QualifiedApiName' + }); + + String queryString = 'SELECT '; + queryString += String.join(new List(indicatorItemsFields),','); + + queryString += ',\n(SELECT '; + queryString += String.join(new List(indicatorItemExtensionFields),',') +' \nFROM '+getItemExtensionRelationShip().getRelationshipName(); + queryString += ' \nWHERE '+indicatorItemExtension_Field_Delete.getDescribe().getName()+' != TRUE'; + queryString += ' \nORDER BY '+indicatorItemExtension_Field_Priority.getDescribe().getName()+' ASC NULLS LAST)'; + + queryString += ' \nFROM '+Indicator_Item__mdt.SObjectType.getDescribe().getName(); + queryString += ' \nWHERE '+indicatorItem_Field_Delete.getDescribe().getName()+' != TRUE'; + queryString += ' \nAND '+indicatorItem_Field_sObject.getDescribe().getName()+' = :sObjectName'; + + queryString += ' \nORDER BY '+indicatorItem_Field_Field.getDescribe().getName()+' ASC'; + + Map queryBindMap = new Map{ + 'sObjectName' => sObjectName + }; + AccessLevel level = (Test.isRunningTest()) ? AccessLevel.SYSTEM_MODE : AccessLevel.USER_MODE; /**For Testing only we allow all fields**/ + return Database.queryWithBinds(queryString,queryBindMap,level); + } + + public class indicatorBundle { + @AuraEnabled + public Indicator_Bundle__mdt bundle; + @AuraEnabled + public List allItems; + + public indicatorBundle(String qualifiedApiName) { + this.bundle = getIndicatorBundle(qualifiedApiName); + if(this.bundle != null) this.allItems = getAllIndicatorItems(this.bundle.sObject__c); + } + } + +} \ No newline at end of file diff --git a/force-app/main/default/classes/MetadataUtility.cls-meta.xml b/force-app/main/default/classes/MetadataUtility.cls-meta.xml new file mode 100644 index 0000000..fbbad0a --- /dev/null +++ b/force-app/main/default/classes/MetadataUtility.cls-meta.xml @@ -0,0 +1,5 @@ + + + 56.0 + Active + diff --git a/force-app/main/default/classes/ObjectFieldSelectorController.cls b/force-app/main/default/classes/ObjectFieldSelectorController.cls new file mode 100644 index 0000000..8c32eb4 --- /dev/null +++ b/force-app/main/default/classes/ObjectFieldSelectorController.cls @@ -0,0 +1,116 @@ +public with sharing class ObjectFieldSelectorController { + + public static final String STANDARD = 'standard'; + public static final String SPECIFIC = 'specific'; + public static final String CUSTOM = 'custom'; + public static final String BOTH = 'both'; + public static final String ANCILLARY = 'ancillary'; + public static final String ALL = 'all'; + + @AuraEnabled + public static GetObjectsResult getObjects(String selectionType, List availableObjects) { + if (String.isBlank(selectionType)) + selectionType = BOTH; + selectionType = selectionType.toLowerCase(); + GetObjectsResult result = new GetObjectsResult(); + result.objects = new List(); + List describeResults = new List(); + if (selectionType == ALL) { + Map objMap = Schema.getGlobalDescribe(); + for (Schema.SObjectType objType : objMap.values()) { + describeResults.add(objType.getDescribe()); + } + } else if (selectionType == SPECIFIC) { + describeResults = Schema.describeSObjects(availableObjects); + } else { + List objectNames = new List(); + List entityDefs = new List(); + if (selectionType == STANDARD || selectionType == BOTH) { + entityDefs.addAll([SELECT KeyPrefix, QualifiedApiName, DeveloperName FROM EntityDefinition WHERE (NOT QualifiedApiName LIKE '%__c') AND (NOT QualifiedApiName LIKE '%Feed') AND (NOT QualifiedApiName LIKE '%Tag') AND (NOT QualifiedApiName LIKE '%Share') AND (NOT QualifiedApiName LIKE '%ChangeEvent') AND (NOT QualifiedApiName LIKE '%History')]); + } + if (selectionType == CUSTOM || selectionType == BOTH) { + entityDefs.addAll([SELECT QualifiedApiName FROM EntityDefinition WHERE QualifiedApiName LIKE '%__c']); + } + if (selectionType == ANCILLARY) { + entityDefs.addAll([SELECT QualifiedApiName, DeveloperName FROM EntityDefinition WHERE QualifiedApiName LIKE '%Feed' OR QualifiedApiName LIKE '%Tag' OR QualifiedApiName LIKE '%Share' OR QualifiedApiName LIKE '%ChangeEvent' OR QualifiedApiName LIKE '%History']); + } + for (EntityDefinition def : entityDefs) { + // The standard list of EntityDefinitions may still return some odd types like metadata, so we filter out any object with double underscores + if (selectionType != STANDARD || !def.QualifiedApiName.contains('__')) { + objectNames.add(def.QualifiedApiName); + } + } + describeResults = Schema.describeSObjects(objectNames); + } + for (Schema.DescribeSObjectResult res : describeResults) { + result.objects.add(new ObjectResult(res.getLabel(), res.getName())); + } + return result; + } + + @AuraEnabled(cacheable=true) + public static GetObjectFieldsResult getObjectFields(String objectName) { + GetObjectFieldsResult result = new GetObjectFieldsResult(); + result.fields = new List(); + try { + Map tokenMap = ((SObject)Type.forName('Schema', objectName).newInstance()).getSObjectType().getDescribe().fields.getMap(); + for (Schema.SObjectField objField : tokenMap.values()) { + FieldResult newField = new FieldResult(objField.getDescribe()); + System.debug(newField); + result.fields.add(newField); + } + } catch (Exception e) { + result.errorMessage = e.getMessage(); + return result; + } + System.debug('about to return result, with '+ result.fields.size() +' fields'); + return result; + } + + public class GetObjectsResult { + @AuraEnabled public List objects; + } + + public class ObjectResult { + @AuraEnabled public String label; + @AuraEnabled public String value; + + public ObjectResult(String label, String value) { + this.label = label; + this.value = value; + } + } + + public class GetObjectFieldsResult { + @AuraEnabled public String errorMessage; + @AuraEnabled public List fields; + } + + public class FieldResult { + @AuraEnabled public String apiName; + @AuraEnabled public String label; + @AuraEnabled public String dataType; + @AuraEnabled public boolean nameField; + @AuraEnabled public List referenceToInfos; + + public FieldResult(Schema.DescribeFieldResult fieldResult) { + this.apiName = fieldResult.getName(); + this.label = fieldResult.getLabel(); + this.dataType = fieldResult.getType().name(); + this.nameField = fieldResult.isNameField(); + List refToInfos = new List(); + for (Schema.sObjectType objType : fieldResult.getReferenceTo()) { + refToInfos.add(new ReferenceToInfo(objType.getDescribe().getName())); + } + this.referenceToInfos = refToInfos; + } + } + + public class ReferenceToInfo { + @AuraEnabled public String apiName; + + public ReferenceToInfo(String apiName) { + this.apiName = apiName; + } + } +} diff --git a/force-app/main/default/classes/ObjectFieldSelectorController.cls-meta.xml b/force-app/main/default/classes/ObjectFieldSelectorController.cls-meta.xml new file mode 100644 index 0000000..40d6793 --- /dev/null +++ b/force-app/main/default/classes/ObjectFieldSelectorController.cls-meta.xml @@ -0,0 +1,5 @@ + + + 54.0 + Active + diff --git a/force-app/main/default/classes/ObjectFieldSelectorControllerTest.cls b/force-app/main/default/classes/ObjectFieldSelectorControllerTest.cls new file mode 100644 index 0000000..8c0cb53 --- /dev/null +++ b/force-app/main/default/classes/ObjectFieldSelectorControllerTest.cls @@ -0,0 +1,18 @@ +@isTest +public class ObjectFieldSelectorControllerTest { + + @isTest + public static void testOFSController() { + ObjectFieldSelectorController.GetObjectsResult result1 = ObjectFieldSelectorController.getObjects('all', new List()); + ObjectFieldSelectorController.GetObjectsResult result2 = ObjectFieldSelectorController.getObjects('both', new List()); + ObjectFieldSelectorController.GetObjectsResult result3 = ObjectFieldSelectorController.getObjects('specific', new List{'Account', 'Opportunity'}); + System.assertEquals(result3.objects.size(), 2); + System.assert(result3.objects.size() < result2.objects.size()); + System.assert(result2.objects.size() < result1.objects.size()); + + ObjectFieldSelectorController.GetObjectFieldsResult result4 = ObjectFieldSelectorController.getObjectFields('Account'); + ObjectFieldSelectorController.GetObjectFieldsResult result5 = ObjectFieldSelectorController.getObjectFields('NotARealObject'); + System.assert(String.isBlank(result4.errorMessage)); + System.assert(!String.isBlank(result5.errorMessage)); + } +} diff --git a/force-app/main/default/classes/ObjectFieldSelectorControllerTest.cls-meta.xml b/force-app/main/default/classes/ObjectFieldSelectorControllerTest.cls-meta.xml new file mode 100644 index 0000000..40d6793 --- /dev/null +++ b/force-app/main/default/classes/ObjectFieldSelectorControllerTest.cls-meta.xml @@ -0,0 +1,5 @@ + + + 54.0 + Active + diff --git a/force-app/main/default/classes/SldsIconController.cls b/force-app/main/default/classes/SldsIconController.cls new file mode 100644 index 0000000..16a7ead --- /dev/null +++ b/force-app/main/default/classes/SldsIconController.cls @@ -0,0 +1,69 @@ +public with sharing class SldsIconController { + + static final String COMMA = ','; + static final String NEWLINE = '\r\n'; + static final String SPACE = ' '; + + public class Option { + @AuraEnabled + public String label {get; set;} + @AuraEnabled + public String value {get; set;} + @AuraEnabled + public String icon {get; set;} + } + + @AuraEnabled (cacheable=true) + public static List