19
19
20
20
import {
21
21
DASHBOARD_UI_FILTER_CONFIG_URL_PARAM_KEY ,
22
- IFRAME_COMMS_MESSAGE_TYPE
22
+ IFRAME_COMMS_MESSAGE_TYPE ,
23
23
} from './const' ;
24
24
25
25
// We can swap this out for the actual switchboard package once it gets published
@@ -34,51 +34,61 @@ import { getGuestTokenRefreshTiming } from './guestTokenRefresh';
34
34
export type GuestTokenFetchFn = ( ) => Promise < string > ;
35
35
36
36
export type UiConfigType = {
37
- hideTitle ?: boolean
38
- hideTab ?: boolean
39
- hideChartControls ?: boolean
40
- emitDataMasks ?: boolean
37
+ hideTitle ?: boolean ;
38
+ hideTab ?: boolean ;
39
+ hideChartControls ?: boolean ;
40
+ emitDataMasks ?: boolean ;
41
41
filters ?: {
42
- [ key : string ] : boolean | undefined
43
- visible ?: boolean
44
- expanded ?: boolean
45
- }
42
+ [ key : string ] : boolean | undefined ;
43
+ visible ?: boolean ;
44
+ expanded ?: boolean ;
45
+ } ;
46
46
urlParams ?: {
47
- [ key : string ] : any
48
- }
49
- }
47
+ [ key : string ] : any ;
48
+ } ;
49
+ } ;
50
50
51
51
export type EmbedDashboardParams = {
52
52
/** The id provided by the embed configuration UI in Superset */
53
- id : string
53
+ id : string ;
54
54
/** The domain where Superset can be located, with protocol, such as: https://superset.example.com */
55
- supersetDomain : string
55
+ supersetDomain : string ;
56
56
/** The html element within which to mount the iframe */
57
- mountPoint : HTMLElement
57
+ mountPoint : HTMLElement ;
58
58
/** A function to fetch a guest token from the Host App's backend server */
59
- fetchGuestToken : GuestTokenFetchFn
59
+ fetchGuestToken : GuestTokenFetchFn ;
60
60
/** The dashboard UI config: hideTitle, hideTab, hideChartControls, filters.visible, filters.expanded **/
61
- dashboardUiConfig ?: UiConfigType
61
+ dashboardUiConfig ?: UiConfigType ;
62
62
/** Are we in debug mode? */
63
- debug ?: boolean
63
+ debug ?: boolean ;
64
64
/** The iframe title attribute */
65
- iframeTitle ?: string
65
+ iframeTitle ?: string ;
66
66
/** additional iframe sandbox attributes ex (allow-top-navigation, allow-popups-to-escape-sandbox) **/
67
- iframeSandboxExtras ?: string [ ]
67
+ iframeSandboxExtras ?: string [ ] ;
68
68
/** force a specific refererPolicy to be used in the iframe request **/
69
- referrerPolicy ?: ReferrerPolicy
70
- }
69
+ referrerPolicy ?: ReferrerPolicy ;
70
+ } ;
71
71
72
72
export type Size = {
73
- width : number , height : number
74
- }
73
+ width : number ;
74
+ height : number ;
75
+ } ;
75
76
77
+ export type ObserveDataMaskCallbackFn = (
78
+ dataMask : Record < string , any > & {
79
+ crossFiltersChanged : boolean ;
80
+ nativeFiltersChanged : boolean ;
81
+ } ,
82
+ ) => void ;
76
83
export type EmbeddedDashboard = {
77
84
getScrollSize : ( ) => Promise < Size > ;
78
85
unmount : ( ) => void ;
79
86
getDashboardPermalink : ( anchor : string ) => Promise < string > ;
80
87
getActiveTabs : ( ) => Promise < string [ ] > ;
81
- getDataMasks : ( callbackFn : ( dataMasks : any [ ] ) => void ) => void ;
88
+ observeDataMask : (
89
+ callbackFn : ObserveDataMaskCallbackFn ,
90
+ ) => void ;
91
+ getDataMask : ( ) => Record < string , any > ;
82
92
} ;
83
93
84
94
/**
@@ -91,7 +101,7 @@ export async function embedDashboard({
91
101
fetchGuestToken,
92
102
dashboardUiConfig,
93
103
debug = false ,
94
- iframeTitle = " Embedded Dashboard" ,
104
+ iframeTitle = ' Embedded Dashboard' ,
95
105
iframeSandboxExtras = [ ] ,
96
106
referrerPolicy,
97
107
} : EmbedDashboardParams ) : Promise < EmbeddedDashboard > {
@@ -103,55 +113,67 @@ export async function embedDashboard({
103
113
104
114
log ( 'embedding' ) ;
105
115
106
- if ( supersetDomain . endsWith ( "/" ) ) {
116
+ if ( supersetDomain . endsWith ( '/' ) ) {
107
117
supersetDomain = supersetDomain . slice ( 0 , - 1 ) ;
108
118
}
109
119
110
120
function calculateConfig ( ) {
111
- let configNumber = 0
112
- if ( dashboardUiConfig ) {
113
- if ( dashboardUiConfig . hideTitle ) {
114
- configNumber += 1
121
+ let configNumber = 0 ;
122
+ if ( dashboardUiConfig ) {
123
+ if ( dashboardUiConfig . hideTitle ) {
124
+ configNumber += 1 ;
115
125
}
116
- if ( dashboardUiConfig . hideTab ) {
117
- configNumber += 2
126
+ if ( dashboardUiConfig . hideTab ) {
127
+ configNumber += 2 ;
118
128
}
119
- if ( dashboardUiConfig . hideChartControls ) {
120
- configNumber += 8
129
+ if ( dashboardUiConfig . hideChartControls ) {
130
+ configNumber += 8 ;
121
131
}
122
132
if ( dashboardUiConfig . emitDataMasks ) {
123
- configNumber += 16
133
+ configNumber += 16 ;
124
134
}
125
135
}
126
- return configNumber
136
+ return configNumber ;
127
137
}
128
138
129
139
async function mountIframe ( ) : Promise < Switchboard > {
130
140
return new Promise ( resolve => {
131
141
const iframe = document . createElement ( 'iframe' ) ;
132
- const dashboardConfigUrlParams = dashboardUiConfig ? { uiConfig : `${ calculateConfig ( ) } ` } : undefined ;
133
- const filterConfig = dashboardUiConfig ?. filters || { }
134
- const filterConfigKeys = Object . keys ( filterConfig )
135
- const filterConfigUrlParams = Object . fromEntries ( filterConfigKeys . map (
136
- key => [ DASHBOARD_UI_FILTER_CONFIG_URL_PARAM_KEY [ key ] , filterConfig [ key ] ] ) )
142
+ const dashboardConfigUrlParams = dashboardUiConfig
143
+ ? { uiConfig : `${ calculateConfig ( ) } ` }
144
+ : undefined ;
145
+ const filterConfig = dashboardUiConfig ?. filters || { } ;
146
+ const filterConfigKeys = Object . keys ( filterConfig ) ;
147
+ const filterConfigUrlParams = Object . fromEntries (
148
+ filterConfigKeys . map ( key => [
149
+ DASHBOARD_UI_FILTER_CONFIG_URL_PARAM_KEY [ key ] ,
150
+ filterConfig [ key ] ,
151
+ ] ) ,
152
+ ) ;
137
153
138
154
// Allow url query parameters from dashboardUiConfig.urlParams to override the ones from filterConfig
139
- const urlParams = { ...dashboardConfigUrlParams , ...filterConfigUrlParams , ...dashboardUiConfig ?. urlParams }
140
- const urlParamsString = Object . keys ( urlParams ) . length ? '?' + new URLSearchParams ( urlParams ) . toString ( ) : ''
155
+ const urlParams = {
156
+ ...dashboardConfigUrlParams ,
157
+ ...filterConfigUrlParams ,
158
+ ...dashboardUiConfig ?. urlParams ,
159
+ } ;
160
+ const urlParamsString = Object . keys ( urlParams ) . length
161
+ ? '?' + new URLSearchParams ( urlParams ) . toString ( )
162
+ : '' ;
141
163
142
164
// set up the iframe's sandbox configuration
143
- iframe . sandbox . add ( " allow-same-origin" ) ; // needed for postMessage to work
144
- iframe . sandbox . add ( " allow-scripts" ) ; // obviously the iframe needs scripts
145
- iframe . sandbox . add ( " allow-presentation" ) ; // for fullscreen charts
146
- iframe . sandbox . add ( " allow-downloads" ) ; // for downloading charts as image
147
- iframe . sandbox . add ( " allow-forms" ) ; // for forms to submit
148
- iframe . sandbox . add ( " allow-popups" ) ; // for exporting charts as csv
165
+ iframe . sandbox . add ( ' allow-same-origin' ) ; // needed for postMessage to work
166
+ iframe . sandbox . add ( ' allow-scripts' ) ; // obviously the iframe needs scripts
167
+ iframe . sandbox . add ( ' allow-presentation' ) ; // for fullscreen charts
168
+ iframe . sandbox . add ( ' allow-downloads' ) ; // for downloading charts as image
169
+ iframe . sandbox . add ( ' allow-forms' ) ; // for forms to submit
170
+ iframe . sandbox . add ( ' allow-popups' ) ; // for exporting charts as csv
149
171
// additional sandbox props
150
172
iframeSandboxExtras . forEach ( ( key : string ) => {
151
173
iframe . sandbox . add ( key ) ;
152
174
} ) ;
153
175
// force a specific refererPolicy to be used in the iframe request
154
- if ( referrerPolicy ) {
176
+ if ( referrerPolicy ) {
155
177
iframe . referrerPolicy = referrerPolicy ;
156
178
}
157
179
@@ -167,20 +189,26 @@ export async function embedDashboard({
167
189
// See https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
168
190
// we know the content window isn't null because we are in the load event handler.
169
191
iframe . contentWindow ! . postMessage (
170
- { type : IFRAME_COMMS_MESSAGE_TYPE , handshake : " port transfer" } ,
192
+ { type : IFRAME_COMMS_MESSAGE_TYPE , handshake : ' port transfer' } ,
171
193
supersetDomain ,
172
194
[ theirPort ] ,
173
- )
195
+ ) ;
174
196
log ( 'sent message channel to the iframe' ) ;
175
197
176
198
// return our port from the promise
177
- resolve ( new Switchboard ( { port : ourPort , name : 'superset-embedded-sdk' , debug } ) ) ;
199
+ resolve (
200
+ new Switchboard ( {
201
+ port : ourPort ,
202
+ name : 'superset-embedded-sdk' ,
203
+ debug,
204
+ } ) ,
205
+ ) ;
178
206
} ) ;
179
207
iframe . src = `${ supersetDomain } /embedded/${ id } ${ urlParamsString } ` ;
180
208
iframe . title = iframeTitle ;
181
209
//@ts -ignore
182
210
mountPoint . replaceChildren ( iframe ) ;
183
- log ( 'placed the iframe' )
211
+ log ( 'placed the iframe' ) ;
184
212
} ) ;
185
213
}
186
214
@@ -210,17 +238,20 @@ export async function embedDashboard({
210
238
const getDashboardPermalink = ( anchor : string ) =>
211
239
ourPort . get < string > ( 'getDashboardPermalink' , { anchor } ) ;
212
240
const getActiveTabs = ( ) => ourPort . get < string [ ] > ( 'getActiveTabs' ) ;
213
- const getDataMasks = ( callbackFn : ( dataMasks : any [ ] ) => void ) => {
241
+ const getDataMask = ( ) => ourPort . get < Record < string , any > > ( 'getDataMask' ) ;
242
+ const observeDataMask = (
243
+ callbackFn : ObserveDataMaskCallbackFn ,
244
+ ) => {
214
245
ourPort . start ( ) ;
215
- ourPort . defineMethod ( "getDataMasks" , callbackFn ) ;
246
+ ourPort . defineMethod ( 'observeDataMask' , callbackFn ) ;
216
247
} ;
217
248
218
-
219
249
return {
220
250
getScrollSize,
221
251
unmount,
222
252
getDashboardPermalink,
223
253
getActiveTabs,
224
- getDataMasks,
254
+ observeDataMask,
255
+ getDataMask,
225
256
} ;
226
257
}
0 commit comments