I’m embedding dashboard and generative QnA for registered users on a react app with python api generating the embed url. The dashboard embedding is working fine, but the generative QnA iframe is completely blank. When I open the generated link from the api on the browser, it’s also completely blank.
Appreciate any help.
Here is the function i’m using to get embed url.
def get_searchbar_embed_url(
self,
topic_id: str,
user_role: Optional[str] = "READER",
) -> Optional[str]:
"""
Generate an embed URL for the Quick Sight searchbar.
:param topic_id: ID of the topic to embed
:param user_role: Quick Sight user role (READER, AUTHOR, or ADMIN)
:return: Searchbar embed URL or None if generation fails
"""
quicksight_client = self.get_client()
try:
self.describe_user(quicksight_client)
except ClientError:
self.register_user(quicksight_client, user_role)
user_arn = f"arn:aws:quicksight:{self.region}:{self.account_id}:user/default/{self.role_name}/{self.session_name}"
try:
response = (
quicksight_client.generate_embed_url_for_registered_user(
AwsAccountId=self.account_id,
UserArn=user_arn,
ExperienceConfiguration={
"GenerativeQnA": {"InitialTopicId": topic_id}
},
SessionLifetimeInMinutes=30,
)
)
return response["EmbedUrl"]
except Exception as e:
print("Error getting dashboard embed url:", e)
return None
The IAM role using here has a policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"quicksight:GenerateEmbedUrlForRegisteredUser"
],
"Resource": [
"arn:aws:quicksight:*:acc-id:user/default/*",
"arn:aws:quicksight:*:acc-id:dashboard/*"
],
"Condition": {
"ForAllValues:StringEquals": {
"quicksight:AllowedEmbeddingDomains": [
"http://localhost:3000",
]
}
}
},
{
"Effect": "Allow",
"Action": [
"quicksight:RegisterUser"
],
"Resource": "arn:aws:quicksight:*:acc-id:user/default/*"
},
{
"Effect": "Allow",
"Action": [
"quicksight:DescribeUser"
],
"Resource": "arn:aws:quicksight:*:acc-id:user/default/*"
},
{
"Effect": "Allow",
"Action": [
"quicksight:DescribeTopic"
],
"Resource": [
"arn:aws:quicksight:our-region:acc-id:topic/our-topic-id"
]
}
]
}
React code:
const qSbarRef = useRef<HTMLDivElement>(null)
useEffect(() => {
const setupQSearchBar = async (
url: string,
searchBarContainer: HTMLDivElement
) => {
try {
const embeddingContext = await createEmbeddingContext({
onChange: (changeEvent, metadata) => {
console.log('Context received a change', changeEvent, metadata)
},
})
const { embedGenerativeQnA } = embeddingContext
const frameOptions: FrameOptions = {
url,
container: searchBarContainer,
height: '38px',
width: '100%',
onChange: (changeEvent, metadata) => {
console.log('Frame change event:', changeEvent)
switch (changeEvent.eventName) {
case 'FRAME_MOUNTED':
console.log('Frame mounted successfully')
break
case 'FRAME_LOADED':
console.log('Frame loaded successfully')
break
case 'ERROR_OCCURRED':
console.error('Frame error:', changeEvent)
break
}
},
}
const contentOptions: GenerativeQnAContentOptions = {
panelOptions: {
panelType: 'SEARCH_BAR',
},
showTopicName: false,
allowTopicSelection: false,
showPinboard: true,
searchPlaceholderText: 'Ask a question about your data...',
onMessage: async (messageEvent, experienceMetadata) => {
console.log('Message event:', messageEvent)
switch (messageEvent.eventName) {
case 'CONTENT_LOADED':
console.log('Content loaded successfully')
break
case 'ERROR_OCCURRED':
console.error('Content error:', messageEvent)
break
case 'Q_SEARCH_OPENED':
console.log('Search opened')
break
case 'Q_SEARCH_FOCUSED':
console.log('Search focused')
break
}
},
}
console.log('Embedding Q search bar with URL:', url)
console.log('Frame options:', frameOptions)
console.log('Content options:', contentOptions)
const res = await embedGenerativeQnA(frameOptions, contentOptions)
console.log('Embed result:', res)
} catch (error) {
console.error('Error setting up Q search bar:', error)
}
}
if (searchbarEmbedUrl && qSbarRef.current) {
setupQSearchBar(searchbarEmbedUrl.url, qSbarRef.current)
}
}, [searchbarEmbedUrl])
return (
<div className="relative flex flex-col gap-4">
// This is not working.
<div
ref={qSbarRef}
style={{ width: '100%', height: '38px' }}
className="[&>iframe]:absolute"
/>
// This is working.
<div
ref={dashboardContainerRef}
style={{ width: '100%', height: '700px' }}
/>
</div>
)
