Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create LWC recipes (Hello & Dynamic Target sObject) for lightning-record-picker #864

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
c6ce30a
boilerplate
arosenbach Oct 10, 2023
a04c2bd
chore: rename entity to target
SimonKempf Oct 10, 2023
3575c06
update sfdx-lwc-jest dependency to have access to lightning-record-pi…
SimonKempf Oct 10, 2023
c9a39e0
feat: create dedicated test for recordPickerDynamicTarget use case
SimonKempf Oct 10, 2023
daaa8aa
display entity selector and record picker ina row
RamiNoufal Oct 10, 2023
2d53379
add a flaxipage in LWC recipes app having RecordPickerDynamicTarget cmp
RamiNoufal Oct 10, 2023
b86008d
clean u html file
RamiNoufal Oct 10, 2023
847e6e5
change component and tab icons
RamiNoufal Oct 10, 2023
99f3ff7
hide the target selector when a record is selected
RamiNoufal Oct 10, 2023
8fd2821
feat: adding new recordPicker cmp for basic use case
SimonKempf Oct 10, 2023
64c3375
add component's source and a tooltip
RamiNoufal Oct 11, 2023
489ce6b
remove fixed widths and use flex shrink instead
RamiNoufal Oct 11, 2023
0d370fe
feat: using contact-tile to display details of the selected record
SimonKempf Oct 11, 2023
df55876
feat: using icon + view-source component
SimonKempf Oct 11, 2023
37f3c2d
move data folder to __tests__
RamiNoufal Oct 11, 2023
db9238d
fix handle change event in recordPickerHello
RamiNoufal Oct 11, 2023
aa28fda
visual improvements
RamiNoufal Oct 11, 2023
3e45773
clean up and remove dead code
RamiNoufal Oct 11, 2023
3dee36d
improve test coverage
RamiNoufal Oct 11, 2023
29acc0b
update flexipage to include recordPickerHello
RamiNoufal Oct 11, 2023
f62924b
remove non relevant files
RamiNoufal Oct 11, 2023
c2b5563
revert changes in package.json + add .npmrc
arosenbach Oct 12, 2023
cad55d7
bump @salesforce/sfdx-lwc-jest to access lightning-record picker (cor…
arosenbach Oct 12, 2023
8f0fbbc
pr comments
arosenbach Oct 12, 2023
2b2166f
remove unnecessary variables
arosenbach Oct 12, 2023
342cb65
add error panel to show getObjectInfos errors
arosenbach Oct 12, 2023
8c52298
add error panel to show graphql errors
arosenbach Oct 12, 2023
7f4697e
remove unnecessary variable
arosenbach Oct 12, 2023
820a2f3
remove getObjectInfos wire
arosenbach Oct 12, 2023
552f504
remove getObjectInfos wire from test
arosenbach Oct 12, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
registry=https://registry.npmjs.org/
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<tabs>Wire</tabs>
<tabs>GraphQL</tabs>
<tabs>Navigation</tabs>
<tabs>Record_Picker</tabs>
<tabs>Misc_Techniques</tabs>
<tabs>X3rd_Party_Libs</tabs>
<uiType>Lightning</uiType>
Expand Down
36 changes: 36 additions & 0 deletions force-app/main/default/flexipages/Record_Picker.flexipage-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" ?>
<FlexiPage xmlns="http://soap.sforce.com/2006/04/metadata">
<flexiPageRegions>
<name>region1</name>
<type>Region</type>
</flexiPageRegions>
<flexiPageRegions>
<itemInstances>
<componentInstance>
<componentName>recordPickerHello</componentName>
<identifier>c_recordPickerHello</identifier>
</componentInstance>
</itemInstances>
<name>region2</name>
<type>Region</type>
</flexiPageRegions>
<flexiPageRegions>
<itemInstances>
<componentInstance>
<componentName>recordPickerDynamicTarget</componentName>
<identifier>c_recordPickerDynamicTarget</identifier>
</componentInstance>
</itemInstances>
<name>region3</name>
<type>Region</type>
</flexiPageRegions>
<flexiPageRegions>
<name>region4</name>
<type>Region</type>
</flexiPageRegions>
<masterLabel>Record Picker</masterLabel>
<template>
<name>flexipage:appHomeTemplateHeaderThreeColumns</name>
</template>
<type>AppPage</type>
</FlexiPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { createElement } from 'lwc';
import RecordPickerDynamicTarget from 'c/recordPickerDynamicTarget';

describe('recordPickerDynamicTarget', () => {
let element;
beforeEach(() => {
// Create component
element = createElement('c-record-picker-dynamic-target', {
is: RecordPickerDynamicTarget
});
element.objectApiName = 'Account';
element.label = 'Account';
document.body.appendChild(element);
});

afterEach(() => {
// The jsdom instance is shared across test cases in a single file so reset the DOM
while (document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
// Prevent data saved on mocks from leaking between tests
jest.clearAllMocks();
});

// Helper function to wait until the microtask queue is empty. This is needed for promise
// timing when calling imperative Apex.
async function flushPromises() {
return Promise.resolve();
}

it('renders a lightning-record-picker component', () => {
const recordPickerElement = element.shadowRoot.querySelector(
'lightning-record-picker'
);
expect(recordPickerElement).toBeTruthy();
});

it('is accessible', async () => {
expect(element).toBeAccessible();
});

it('changes the target object of the record picker', async () => {
// Change the target object
const targetSelector = element.shadowRoot.querySelector(
'[data-id="targetSelector"]'
);
targetSelector.value = 'Case';
targetSelector.dispatchEvent(new CustomEvent('change'));

// Wait for any asynchronous DOM updates
await flushPromises();

// Check that the target object of the record picker has been updated
const recordPickerElement = element.shadowRoot.querySelector(
'lightning-record-picker'
);
expect(recordPickerElement.objectApiName).toBe('Case');
});

it('hides the target selector when a record is selected', async () => {
const recordPickerElement = element.shadowRoot.querySelector(
'lightning-record-picker'
);

// Simulate a record selection in the record picker
recordPickerElement.dispatchEvent(
new CustomEvent('change', {
detail: { recordId: '0017a00002PJIloAAH' }
})
);

// Wait for any asynchronous DOM updates
await flushPromises();

// Check that the target selector is not displayed anymore
const targetSelector = element.shadowRoot.querySelector(
'[data-id="targetSelector"]'
);
expect(targetSelector).toBeFalsy();
});

it('displays the target selector again after clearing the selected record', async () => {
const recordPickerElement = element.shadowRoot.querySelector(
'lightning-record-picker'
);
// Simulate a record selection in the record picker
recordPickerElement.dispatchEvent(
new CustomEvent('change', {
detail: { recordId: '0017a00002PJIloAAH' }
})
);

// Wait for any asynchronous DOM updates
await flushPromises();

// Simulate clearing the selected record' in the record picker
recordPickerElement.dispatchEvent(
new CustomEvent('change', { detail: { recordId: null } })
);

// Wait for any asynchronous DOM updates
await flushPromises();

// Check that the target selector is not displayed anymore
const targetSelector = element.shadowRoot.querySelector(
'[data-id="targetSelector"]'
);
expect(targetSelector).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<template>
<lightning-card
title="RecordPickerDynamicTarget"
class="slds-card__body_inner"
icon-name="standard:search"
>
<div class="slds-form-element">
<label class="slds-form-element__label">Select a record</label>
<div class="slds-form-element__control slds-combobox-group">
<template if:true={showTargetSelector}>
<lightning-combobox
data-id="targetSelector"
label="Select a target sObject"
variant="label-hidden"
options={targetObjects}
value={selectedTarget}
onchange={handleTargetSelection}
class="slds-combobox_object-switcher slds-combobox-addon_start"
>
</lightning-combobox>
</template>
<lightning-record-picker
lwc:ref="recordPicker"
object-api-name={selectedTarget}
placeholder="Search..."
label="Select a record"
variant="label-hidden"
display-info={displayInfo}
matching-info={matchingInfo}
onchange={handleRecordSelect}
class="slds-size_full slds-combobox-addon_end"
>
</lightning-record-picker>
</div>
</div>
<c-view-source source="lwc/recordPickerDynamicTarget" slot="footer">
Select a target sObject. Type a search term and select a record.
pozil marked this conversation as resolved.
Show resolved Hide resolved
</c-view-source>
</lightning-card>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { LightningElement } from 'lwc';

export default class RecordPickerDynamicTarget extends LightningElement {
targetObjects = [
{
label: 'Account',
value: 'Account'
},
{
label: 'Contact',
value: 'Contact'
}
];
selectedTarget = 'Account';
currentSelectedRecordId = null;

displayInfos = {
Account: {
additionalFields: ['Type']
},
Contact: {
additionalFields: ['Phone']
}
};

matchingInfos = {
Account: {
additionalFields: [{ fieldPath: 'Type' }]
},
Contact: {
additionalFields: [{ fieldPath: 'Phone' }]
}
};

get displayInfo() {
return this.displayInfos[this.selectedTarget];
}

get matchingInfo() {
return this.matchingInfos[this.selectedTarget];
}

get showTargetSelector() {
return this.currentSelectedRecordId === null;
}

handleTargetSelection(event) {
this.selectedTarget = event.target.value;
this.refs.recordPicker.clearSelection();
}

handleRecordSelect(event) {
this.currentSelectedRecordId = event.detail.recordId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>59.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__RecordAction</target>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
<target>lightning__Tab</target>
<target>lightningCommunity__Page</target>
<target>lightningCommunity__Default</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__RecordAction">
<actionType>ScreenAction</actionType>
</targetConfig>
<targetConfig targets="lightning__RecordPage">
<supportedFormFactors>
<supportedFormFactor type="Small" />
<supportedFormFactor type="Large" />
</supportedFormFactors>
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"uiapi": {
"query": {
"Contact": {
"edges": []
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"uiapi": {
"query": {
"Contact": {
"edges": [
{
"node": {
"Id": "001xx000016QpSqAAK",
"Name": {
"value": "Amy Taylor"
},
"Title": {
"value": "VP of Engineering"
},
"Phone": {
"value": "4152568563"
},
"Email": {
"value": "amy@demo.net"
},
"Picture__c": {
"value": "https://s3-us-west-2.amazonaws.com/dev-or-devrl-s3-bucket/sample-apps/people/amy_taylor.jpg"
}
}
}
]
}
}
}
}
Loading