Skip to content

Commit

Permalink
Merge pull request #53 from sfdctaka/compactLayout
Browse files Browse the repository at this point in the history
Get correct compact layout for sObject
  • Loading branch information
sfdctaka committed Nov 15, 2023
2 parents 4030b50 + d62c587 commit 7632f66
Show file tree
Hide file tree
Showing 3 changed files with 238 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/commands/wizard/lwcGenerationCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { InstructionsWebviewProvider } from '../../webviews/instructions';
import { UEMParser } from '../../utils/uemParser';
import { WorkspaceUtils } from '../../utils/workspaceUtils';
import { CommonUtils } from '@salesforce/lwc-dev-mobile-core';
import { OrgUtils } from '../../utils/orgUtils';
import * as fs from 'fs';
import * as path from 'path';

Expand Down Expand Up @@ -82,6 +83,14 @@ export class LwcGenerationCommand {
if (callback) {
const quickActionStatus =
await LwcGenerationCommand.checkForExistingQuickActions();

for (const key in quickActionStatus.sobjects) {
const layoutFields =
await OrgUtils.getCompactLayoutFieldsForSObject(
key
);
}

callback(quickActionStatus);
}
}
Expand Down
126 changes: 126 additions & 0 deletions src/test/suite/utils/orgUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,132 @@ suite('Org Utils Test Suite', () => {
assert.equal(sobject.labelPlural, 'Labels');
});

test('Returns SYSTEM compact layout', async () => {
// Simplified all compact layout data structure
const allCompactLayouts = {
defaultCompactLayoutId: null,
recordTypeCompactLayoutMappings: [
{
available: true,
compactLayoutId: null,
compactLayoutName: 'SYSTEM',
recordTypeId: '012000000000000AAA',
recordTypeName: 'Master',
urls: {
compactLayout:
'/services/data/v59.0/sobjects/Contact/describe/compactLayouts/012000000000000AAA'
}
}
]
};

// Simplified compact layout data structure
const compactLayout = {
fieldItems: [
{
editableForNew: true,
editableForUpdate: true,
label: 'Name'
},
{
editableForNew: true,
editableForUpdate: true,
label: 'Title'
},
{
editableForNew: false,
editableForUpdate: false,
label: 'Contact Owner'
}
],
id: null,
label: 'System Default',
name: 'SYSTEM',
objectType: 'Contact'
};

sinon
.stub(OrgUtils, 'getCompactLayoutsForSObject')
.returns(Promise.resolve(allCompactLayouts));
sinon
.stub(OrgUtils, 'getCompactLayoutForSObject')
.returns(Promise.resolve(compactLayout));

const result =
await OrgUtils.getCompactLayoutFieldsForSObject('Contact');

assert.equal(result, compactLayout.fieldItems);
});

test('Returns Contact compact layout', async () => {
// Simplified all compact layout data structure
const allCompactLayouts = {
defaultCompactLayoutId: '123456789',
recordTypeCompactLayoutMappings: [
{
available: true,
compactLayoutId: null,
compactLayoutName: 'SYSTEM',
recordTypeId: '012000000000000AAA',
recordTypeName: 'Master',
urls: {
compactLayout:
'/services/data/v59.0/sobjects/Contact/describe/compactLayouts/012000000000000AAA'
}
},
{
available: true,
compactLayoutId: '123456789',
compactLayoutName: 'Mobile layout',
recordTypeId: '012000000000000BBB',
recordTypeName: 'Contact',
urls: {
compactLayout:
'/services/data/v59.0/sobjects/Contact/describe/compactLayouts/012000000000000BBB'
}
}
]
};

// Simplified compact layout data structure
const compactLayout = {
fieldItems: [
{
editableForNew: true,
editableForUpdate: true,
label: 'Name'
},
{
editableForNew: true,
editableForUpdate: true,
label: 'Title'
},
{
editableForNew: false,
editableForUpdate: false,
label: 'Contact Owner'
}
],
id: null,
label: 'Mobile layout',
name: 'Mobile layout',
objectType: 'Contact'
};

sinon
.stub(OrgUtils, 'getCompactLayoutsForSObject')
.returns(Promise.resolve(allCompactLayouts));
sinon
.stub(OrgUtils, 'getCompactLayoutForSObject')
.withArgs('Contact', '012000000000000BBB')
.returns(Promise.resolve(compactLayout));

const result =
await OrgUtils.getCompactLayoutFieldsForSObject('Contact');

assert.equal(result, compactLayout.fieldItems);
});

test('Returns list of fields for given sObject', async () => {
const sobjectFields: FieldType[] = [
buildField('City', 'string', 'Label'),
Expand Down
103 changes: 103 additions & 0 deletions src/utils/orgUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,28 @@ export interface Field {
label: string;
type: string;
}

export interface CompactLayoutField {
editableForNew: boolean;
editableForUpdate: boolean;
label: string;
}

export type SObjectCompactLayoutMapping = {
compactLayoutId: string | null;
compactLayoutName: string;
recordTypeId: string;
};

export type SObjectCompactLayouts = {
defaultCompactLayoutId: string | null;
recordTypeCompactLayoutMappings: SObjectCompactLayoutMapping[];
};

export type SObjectCompactLayout = {
fieldItems: CompactLayoutField[];
};

export class OrgUtils {
public static async getSobjects(): Promise<SObject[]> {
try {
Expand Down Expand Up @@ -65,6 +87,87 @@ export class OrgUtils {
}
}

public static async getCompactLayoutsForSObject(
sObjectName: string
): Promise<SObjectCompactLayouts> {
const org = await Org.create();
const conn = org.getConnection();

const result = await conn.request<SObjectCompactLayouts>(
`/services/data/v59.0/sobjects/${sObjectName}/describe/compactLayouts`
);

return Promise.resolve(result);
}

public static async getCompactLayoutForSObject(
sObjectName: string,
recordTypeId: string
): Promise<SObjectCompactLayout> {
const org = await Org.create();
const conn = org.getConnection();

const result = await conn.request<SObjectCompactLayout>(
`/services/data/v59.0/sobjects/${sObjectName}/describe/compactLayouts/${recordTypeId}`
);

return Promise.resolve(result);
}

public static async getCompactLayoutFieldsForSObject(
sObjectName: string
): Promise<CompactLayoutField[]> {
try {
const fields: CompactLayoutField[] = [];

// Get all the compact layouts associated to this sObject first
let result = await this.getCompactLayoutsForSObject(sObjectName);

if (result) {
// sObject can have multiple compact layouts associated with it. Get the default.
const defaultCompactLayoutId = result.defaultCompactLayoutId;
result['defaultCompactLayoutId'];

// Mapping table
const recordTypeCompactLayoutMappings =
result.recordTypeCompactLayoutMappings;

// ID of compact layout need to be normalized
const recordTypeCompactLayoutMapping =
recordTypeCompactLayoutMappings.find((element) => {
if (defaultCompactLayoutId) {
return (
element.compactLayoutId ===
defaultCompactLayoutId
);
} else {
// defaultCompactLayoutId can be null when a compact layout is not assigned.
// In that case sObject will always have one default layout called SYSTEM.
// So use that instead.
return element.compactLayoutName === 'SYSTEM';
}
});

if (recordTypeCompactLayoutMapping) {
// With the compact layout ID mapped back to the recordType ID, make another network request to get the
// exact compact layout info.
const compactLayout = await this.getCompactLayoutForSObject(
sObjectName,
recordTypeCompactLayoutMapping.recordTypeId
);

if (compactLayout) {
return compactLayout.fieldItems;
}
}
}

return Promise.resolve(fields);
} catch (error) {
return Promise.reject(error);
}
}

public static async getDefaultUser(): Promise<string> {
const aggregator = await ConfigAggregator.create();

Expand Down

0 comments on commit 7632f66

Please sign in to comment.