Skip to content

Commit 13d4044

Browse files
authored
Merge branch 'master' into dependabot/npm_and_yarn/webpack-dev-server-5.2.1
2 parents ad36b18 + 968a56c commit 13d4044

68 files changed

Lines changed: 661 additions & 326 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

demo/demo_merge_edit_frame.html

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="UTF-8" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<link href="beer.min.css" rel="stylesheet" />
8+
<link href="demo.css" rel="stylesheet" type="text/css" />
9+
<title>Edit Merge Query</title>
10+
<script src="demo_merge_edit_frame.js"></script>
11+
</head>
12+
13+
<body class="single-frame-container">
14+
<h6 class="main-heading">Edit Merge Query</h6>
15+
<div id="controls" class="grid no-space py-10">
16+
<div class="s6">
17+
</div>
18+
<div class="s6">
19+
<button id="close-merge" class="small-round">Close</button>
20+
</div>
21+
</div>
22+
<div id="embed-status" class="pt-10 py-10 large-text">Loading...</div>
23+
<div id="embed-container"></div>
24+
</body>
25+
26+
</html>

demo/demo_merge_edit_frame.ts

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
3+
MIT License
4+
5+
Copyright (c) 2025 Looker Data Sciences, Inc.
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in all
15+
copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
SOFTWARE.
24+
25+
*/
26+
27+
import type { ILookerConnection, ILookerEmbedSDK } from '../src/index'
28+
import { getEmbedSDK } from '../src/index'
29+
import type { RuntimeConfig } from './demo_config'
30+
import { getConfiguration, loadConfiguration } from './demo_config'
31+
32+
let embedConnection: ILookerConnection
33+
34+
/**
35+
* Save the embed connection. This provides access to the undelying
36+
* functionality of each embed content type.
37+
*/
38+
const embedConnected = (connection: ILookerConnection) => {
39+
embedConnection = connection
40+
updateStatus('')
41+
}
42+
43+
/**
44+
* Update the status for each embedded element
45+
*/
46+
const updateStatus = (status: string) => {
47+
const statusElement = document.querySelector('#embed-status')
48+
if (statusElement) {
49+
if (status) {
50+
statusElement.textContent = status
51+
} else {
52+
statusElement.innerHTML = '&nbsp;'
53+
}
54+
}
55+
}
56+
57+
/**
58+
* Initialize controls.
59+
*/
60+
const initializeControls = () => {
61+
const runButton = document.querySelector('#close-merge')
62+
if (runButton) {
63+
runButton.addEventListener('click', () => {
64+
window.close()
65+
})
66+
}
67+
}
68+
69+
/**
70+
* A canceller callback that prevents the default behavior of edit merge query.
71+
* The default behavior is for the edit merge query page to be opened in a top
72+
* level window.
73+
*/
74+
const openMergeQuery = (event: any): any => {
75+
window.open(`/merge_edit?merge_url=${encodeURI(event.url)}`)
76+
updateStatus('Merge query edit opened in a new window')
77+
return { cancel: true }
78+
}
79+
80+
/**
81+
* The merge edit url is stored in history state
82+
*/
83+
const getEmbedMergeEditUrl = () => {
84+
const embedUrl = decodeURI(history.state?.merge_url || '')
85+
return embedUrl || '/embed/preload'
86+
}
87+
88+
/**
89+
* Render the embedded merge edit page.
90+
*/
91+
const createEmbed = (sdk: ILookerEmbedSDK) => {
92+
const abortController = new AbortController()
93+
const signal = abortController.signal
94+
let timeoutId: any = setTimeout(() => {
95+
abortController.abort(
96+
`Connection attempt timed out. Please check that ${location.origin} has been allow listed`
97+
)
98+
timeoutId = undefined
99+
}, 60000)
100+
sdk
101+
.createWithUrl(getEmbedMergeEditUrl())
102+
.appendTo('#embed-container')
103+
// // Open merge query in its own window
104+
.on('dashboard:tile:merge', openMergeQuery)
105+
.on('session:expired', () => updateStatus('Session Expired'))
106+
.withClassName('looker-embed')
107+
.build()
108+
// Connect to Looker
109+
.connect({ signal, waitUntilLoaded: true })
110+
// Finish up setup
111+
.then((connection) => {
112+
if (timeoutId) {
113+
clearTimeout(timeoutId)
114+
timeoutId = undefined
115+
}
116+
embedConnected(connection)
117+
})
118+
// Log if something went wrong
119+
.catch((error: any) => {
120+
updateStatus(typeof error === 'string' ? error : 'Connection error')
121+
console.error('Connection error', error)
122+
})
123+
}
124+
125+
/**
126+
* Initialize the SDK. lookerHost is the address of the Looker instance. It is configured in
127+
* democonfig.ts. lookerHost needs to be set for messages to be exchanged from the host
128+
* document to the embedded content. The auth endpoint is documented in README.md.
129+
*/
130+
const initializeEmbedSdk = (runtimeConfig: RuntimeConfig) => {
131+
const sdk: ILookerEmbedSDK = getEmbedSDK()
132+
if (runtimeConfig.embedType === 'cookieless') {
133+
// Use cookieless embed
134+
sdk.initCookieless(
135+
runtimeConfig.lookerHost,
136+
`${runtimeConfig.proxyPath}/acquire-embed-session`,
137+
`${runtimeConfig.proxyPath}/generate-embed-tokens`
138+
)
139+
} else if (runtimeConfig.embedType === 'private') {
140+
// Use private embedding
141+
sdk.init(runtimeConfig.lookerHost)
142+
} else {
143+
// Use SSO embed
144+
sdk.init(runtimeConfig.lookerHost, `${runtimeConfig.proxyPath}/auth`)
145+
}
146+
// Now preload the embed
147+
createEmbed(sdk)
148+
}
149+
150+
/**
151+
* Event listener to create embedded content. Waits until DOM is loaded so that
152+
* all the parent elements are present.
153+
*/
154+
document.addEventListener('DOMContentLoaded', function () {
155+
// Hide merge url from end user
156+
const searchParams = new URLSearchParams(location.search)
157+
if (searchParams.has('merge_url')) {
158+
history.replaceState(
159+
{ merge_url: searchParams.get('merge_url') },
160+
'',
161+
location.pathname
162+
)
163+
}
164+
loadConfiguration()
165+
initializeControls()
166+
const runtimeConfig = getConfiguration()
167+
initializeEmbedSdk(runtimeConfig)
168+
})

demo/demo_single_frame.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
// IDs for content to demonstrate can be configured in the .env file or in demo_config.ts
2828

29-
import { connection } from '@looker/sdk'
3029
import type {
3130
ILookerConnection,
3231
ILookerEmbedSDK,
@@ -51,7 +50,16 @@ let currentPathname: string
5150
*/
5251
const embedConnected = (connection: ILookerConnection) => {
5352
embedConnection = connection
54-
updateStatus('')
53+
if (
54+
embedConnection.getLookerMajorVersion() >= 25 &&
55+
embedConnection.getLookerMinorVersion() > 10
56+
) {
57+
updateStatus('')
58+
} else {
59+
updateStatus(
60+
'Listening for event "dashboard:tile:merge" is not supported by the Looker instance'
61+
)
62+
}
5563
}
5664

5765
/**
@@ -108,6 +116,17 @@ const updateStatus = (status: string) => {
108116
}
109117
}
110118

119+
/**
120+
* A canceller callback that prevents the default behavior of edit merge query.
121+
* The default behavior is for the edit merge query page to be opened in a top
122+
* level window.
123+
*/
124+
const openMergeQuery = (event: any): any => {
125+
window.open(`/merge_edit?merge_url=${encodeURI(event.url)}`)
126+
updateStatus('Merge query edit opened in a new window')
127+
return { cancel: true }
128+
}
129+
111130
/**
112131
* A canceller callback can prevent the default behavior of links on a dashboard.
113132
* In this instance, if the click will navigate to a new window, the navigation is
@@ -672,6 +691,8 @@ const createEmbed = (runtimeConfig: RuntimeConfig, sdk: ILookerEmbedSDK) => {
672691
.on('drillmodal:explore', preventNavigation)
673692
.on('dashboard:tile:explore', preventNavigation)
674693
.on('dashboard:tile:view', preventNavigation)
694+
// Open merge query in its own window
695+
.on('dashboard:tile:merge', openMergeQuery)
675696
// Listen to messages to display explore progress
676697
.on('explore:ready', () => updateStatus('Loaded'))
677698
.on('explore:run:start', () => updateStatus('Running'))

docs/assets/search.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)