-
Notifications
You must be signed in to change notification settings - Fork 214
@W-20975885 New launch agent location in header component #3606
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
Changes from 3 commits
2081fa1
c16ea45
f5d1bc2
cabde5a
8ddbd00
c53deb0
0a1f5eb
58f960d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,7 +19,8 @@ export const getCommerceAgentConfig = () => { | |
| commerceOrgId: '', | ||
| siteId: '', | ||
| enableConversationContext: 'false', | ||
| conversationContext: [] | ||
| conversationContext: [], | ||
| enableAgentFromHeader: 'false' | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any idea why the booleans are implemented as strings? I understand this is already there before your change but I'm curious to know if you happen to know the answer.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aggreed its cleaner to use boolean, I'm not sure why the API/Config design uses strings for flags. this is the official help doc Shopper Agent documentation. |
||
| } | ||
| return getConfig().app.commerceAgent ?? defaults | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| /* | ||
| * Copyright (c) 2025, Salesforce, Inc. | ||
| * All rights reserved. | ||
| * SPDX-License-Identifier: BSD-3-Clause | ||
| * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
| */ | ||
| const onClient = typeof window !== 'undefined' | ||
|
|
||
| /** | ||
| * Launch the chat using the embedded service bootstrap API | ||
| * | ||
| * @function launchChat | ||
| * @returns {void} | ||
| */ | ||
| export function launchChat() { | ||
| if (!onClient) return | ||
|
|
||
| try { | ||
| // Launch chat using the embedded service bootstrap API | ||
| if ( | ||
| window.embeddedservice_bootstrap && | ||
| typeof window.embeddedservice_bootstrap.utilAPI.launchChat === 'function' | ||
| ) { | ||
| window.embeddedservice_bootstrap.utilAPI.launchChat() | ||
| } | ||
| } catch (error) { | ||
| console.error('Shopper Agent: Error launching chat', error) | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Open the shopper agent chat window | ||
| * | ||
| * Programmatically opens the embedded messaging widget by finding and clicking | ||
| * the embedded service chat button. This function can be called from custom | ||
| * UI elements like header buttons. | ||
| * | ||
| * @function openShopperAgent | ||
| * @returns {void} | ||
| */ | ||
| export function openShopperAgent() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need both launchChat and openShopperAgent function?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. openShopperAgent will have more conditions once we introduce flag to hide the FAB icon thats why added two seperate functions |
||
| if (!onClient) return | ||
|
|
||
| try { | ||
| launchChat() | ||
| } catch (error) { | ||
| console.error('Shopper Agent: Error opening agent', error) | ||
| } | ||
| } | ||
|
Comment on lines
+7
to
+49
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have you considered to make this a React hook? There are many React hooks in this code base and it 's more consistent with the style and the technologies we used. something like below. import { useCallback } from 'react'
declare global {
interface Window {
embeddedservice_bootstrap?: {
utilAPI: {
launchChat: () => void
}
}
}
}
/**
* Hook for launching the Salesforce Embedded Service chat
*/
export function useShopperAgent() {
const openChat = useCallback(() => {
if (typeof window === 'undefined') return
try {
window.embeddedservice_bootstrap?.utilAPI.launchChat()
} catch (error) {
console.error('Shopper Agent: Error launching chat', error)
}
}, [])
return { openChat }
}usage example function ChatButton() {
const { openChat } = useShopperAgent()
return <button onClick={openChat}>Chat with us</button>
} |
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears the code style is slightly inconsistent, most of the component access the global config object via
getConfig().xxxxxx, and it seems shopper agent introduced its own utilitygetCommerceAgentConfig. I wonder if we want to be consistent, either create utilities for all other features (not just shopper agent), otherwise it looks inconsistent coding styleThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thats a good point, this is where they decided to change it into utility functions, #3230