Skip to content

Commit 587bd7b

Browse files
Update build
1 parent 34b807d commit 587bd7b

4 files changed

Lines changed: 343 additions & 32 deletions

File tree

‎README.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```bash
2+
cd ~/tsft_projects/visual-embed-sdk && npm run build && npx vite build -c vite.local.config.ts --outDir local-dist --base / && rm -rf ~/tsft_projects/ts-nk-github-cplot.github.io/assets && cp local-dist/local/index.html ~/tsft_projects/ts-nk-github-cplot.github.io/index.html && cp -R local-dist/assets ~/tsft_projects/ts-nk-github-cplot.github.io/assets && cp local/index.ts ~/tsft_projects/ts-nk-github-cplot.github.io/assets/index.ts && rm -rf local-dist && git -C ~/tsft_projects/ts-nk-github-cplot.github.io add -A && git -C ~/tsft_projects/ts-nk-github-cplot.github.io commit -m "Update build" && git -C ~/tsft_projects/ts-nk-github-cplot.github.io push
3+
```

‎assets/index.ts‎

Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
import {
2+
Action,
3+
AuthType,
4+
ContextType,
5+
EmbedEvent,
6+
HostEvent,
7+
init,
8+
LiveboardEmbed,
9+
} from '../dist/tsembed.es.js';
10+
11+
init({
12+
thoughtSpotHost: 'https://172.32.101.155:8443',
13+
// thoughtSpotHost: 'https://nebula-agentspotdev.thoughtspotdev.cloud',
14+
// thoughtSpotHost: 'http://localhost:5001/#/',
15+
// authType: AuthType.Basic,
16+
// username: 'tsadmin',
17+
// password: 'pwd',
18+
authType: AuthType.None,
19+
// authType: AuthType.Basic,
20+
// username: 'tsadmin',
21+
// password: 'pwd',
22+
});
23+
24+
// TODO(debug): remove — host-side listener for the
25+
// __debug_hidden_action_config__ postMessage traced from the embedded iframe
26+
// (separate devtools context, so it can't just console.log from in there).
27+
window.addEventListener('message', (event) => {
28+
if (event.data?.type === '__debug_hidden_action_config__') {
29+
console.log('[debug] hidden action config', event.data.data);
30+
}
31+
32+
if (event.data?.type === '__debug_menu_edit_visibility__') {
33+
console.log('[debug] menu EDIT visibility', event.data.data);
34+
}
35+
});
36+
37+
const liveboardId = '9bd202f5-d431-44bf-9a07-b4f7be372125';
38+
39+
const testVizId = 'db0badd5-47c6-400a-842d-133a7b44d435'; // fill in a viz GUID from this Liveboard to test viz-level edit
40+
41+
const app = document.getElementById('app');
42+
43+
const div = document.createElement('div');
44+
div.classList.add('full-liveboard');
45+
app?.appendChild(div);
46+
47+
// TODO(debug): remove — the 9 combos of {hiddenActions, visibleActions,
48+
// disabledActions} x {Action.Edit, Action.EditLiveboard,
49+
// Action.EditVisualization} being validated for the Edit-action split. Each
50+
// one destroys and recreates the embed so the dropdown covers all 9 without
51+
// a rebuild/reload per combo.
52+
const editActionConfigs: Record<
53+
string,
54+
Partial<Record<'hiddenActions' | 'visibleActions' | 'disabledActions', Action[]>>
55+
> = {
56+
None: {},
57+
'hiddenActions: [Action.Edit]': { hiddenActions: [Action.Edit] },
58+
'hiddenActions: [Action.EditVisualization]': { hiddenActions: [Action.EditVisualization] },
59+
'hiddenActions: [Action.EditLiveboard]': { hiddenActions: [Action.EditLiveboard] },
60+
'visibleActions: [Action.Edit]': { visibleActions: [Action.Edit] },
61+
'visibleActions: [Action.EditVisualization]': { visibleActions: [Action.EditVisualization] },
62+
'visibleActions: [Action.EditLiveboard]': { visibleActions: [Action.EditLiveboard] },
63+
'disabledActions: [Action.Edit]': { disabledActions: [Action.Edit] },
64+
'disabledActions: [Action.EditVisualization]': { disabledActions: [Action.EditVisualization] },
65+
'disabledActions: [Action.EditLiveboard]': { disabledActions: [Action.EditLiveboard] },
66+
};
67+
68+
// TODO(debug): remove — floating event console. Replaces the alert() calls so a
69+
// burst of events doesn't need one dismissal each.
70+
const debugConsole = document.createElement('div');
71+
Object.assign(debugConsole.style, {
72+
position: 'fixed',
73+
bottom: '12px',
74+
right: '12px',
75+
width: '380px',
76+
background: '#1e1e1e',
77+
color: '#ddd',
78+
font: '11px/1.4 monospace',
79+
borderRadius: '6px',
80+
boxShadow: '0 2px 12px rgba(0,0,0,0.4)',
81+
zIndex: '9999',
82+
overflow: 'hidden',
83+
});
84+
document.body.appendChild(debugConsole);
85+
86+
const debugHeader = document.createElement('div');
87+
Object.assign(debugHeader.style, {
88+
display: 'flex',
89+
alignItems: 'center',
90+
gap: '8px',
91+
padding: '6px 8px',
92+
background: '#2d2d2d',
93+
cursor: 'pointer',
94+
userSelect: 'none',
95+
});
96+
debugConsole.appendChild(debugHeader);
97+
98+
const debugTitle = document.createElement('span');
99+
debugTitle.textContent = 'Event console';
100+
debugTitle.style.flex = '1';
101+
debugHeader.appendChild(debugTitle);
102+
103+
const allEventsLabel = document.createElement('label');
104+
allEventsLabel.style.display = 'flex';
105+
allEventsLabel.style.alignItems = 'center';
106+
allEventsLabel.style.gap = '4px';
107+
allEventsLabel.title = 'Log EmbedEvent.ALL';
108+
const allEventsCheckbox = document.createElement('input');
109+
allEventsCheckbox.type = 'checkbox';
110+
allEventsCheckbox.checked = true;
111+
allEventsLabel.appendChild(allEventsCheckbox);
112+
allEventsLabel.appendChild(document.createTextNode('ALL'));
113+
debugHeader.appendChild(allEventsLabel);
114+
115+
const clearButton = document.createElement('button');
116+
clearButton.textContent = 'Clear';
117+
debugHeader.appendChild(clearButton);
118+
119+
const collapseButton = document.createElement('button');
120+
collapseButton.textContent = '\u2013';
121+
collapseButton.style.width = '22px';
122+
debugHeader.appendChild(collapseButton);
123+
124+
const debugLog = document.createElement('div');
125+
Object.assign(debugLog.style, {
126+
maxHeight: '40vh',
127+
overflowY: 'auto',
128+
padding: '4px 0',
129+
});
130+
debugConsole.appendChild(debugLog);
131+
132+
// Header clicks toggle, so the controls inside it must not bubble up.
133+
[allEventsLabel, clearButton].forEach((el) => {
134+
el.onclick = (event) => event.stopPropagation();
135+
});
136+
allEventsCheckbox.onchange = (event) => event.stopPropagation();
137+
clearButton.onclick = (event) => {
138+
event.stopPropagation();
139+
debugLog.replaceChildren();
140+
};
141+
142+
const toggleCollapsed = () => {
143+
const collapsed = debugLog.style.display === 'none';
144+
debugLog.style.display = collapsed ? '' : 'none';
145+
collapseButton.textContent = collapsed ? '\u2013' : '+';
146+
};
147+
collapseButton.onclick = toggleCollapsed;
148+
debugHeader.onclick = toggleCollapsed;
149+
150+
const logEvent = (name: string, payload: unknown) => {
151+
const entry = document.createElement('div');
152+
Object.assign(entry.style, {
153+
padding: '4px 8px',
154+
borderBottom: '1px solid #333',
155+
whiteSpace: 'pre-wrap',
156+
wordBreak: 'break-word',
157+
});
158+
let body: string;
159+
try {
160+
body = JSON.stringify(payload, null, 2) ?? String(payload);
161+
} catch {
162+
body = '<unserializable payload — see devtools>';
163+
}
164+
entry.textContent = `[${new Date().toLocaleTimeString()}] ${name}\n${body}`;
165+
debugLog.appendChild(entry);
166+
debugLog.scrollTop = debugLog.scrollHeight;
167+
};
168+
169+
let liveboardEmbed: LiveboardEmbed;
170+
let isLiveboardHeaderV2Enabled = true;
171+
let showLiveboardTitle = false;
172+
let isLiveboardMasterpiecesEnabled = false;
173+
let isLiveboardCompactHeaderEnabled = false;
174+
175+
// No vizId -> embeds the whole Liveboard, not a single tile.
176+
function renderLiveboard(actionConfig: (typeof editActionConfigs)[string]) {
177+
liveboardEmbed?.destroy();
178+
179+
liveboardEmbed = new LiveboardEmbed(div, {
180+
liveboardId,
181+
fullHeight: true,
182+
minimumHeight: 600,
183+
frameParams: { width: '100%' },
184+
showPreviewLoader: true,
185+
enableV2Shell_experimental: true,
186+
showLiveboardTitle,
187+
isLiveboardMasterpiecesEnabled,
188+
isLiveboardCompactHeaderEnabled,
189+
190+
...actionConfig,
191+
192+
additionalFlags: {
193+
isLiveboardHeaderV2Enabled,
194+
isReorderedEllipsisMenuEnabled: true,
195+
},
196+
});
197+
liveboardEmbed.on(EmbedEvent.Data, () => {
198+
console.log('Liveboard rendered');
199+
});
200+
// TODO(debug): remove — EmbedEvent.EditLiveboard / EditVisualization are
201+
// NOT real SDK enum members today (confirmed against the docs) — only
202+
// EmbedEvent.Edit exists, firing for both the Liveboard-level and
203+
// viz-level Edit action. These two listeners are registered anyway,
204+
// purely to mirror the Action.EditLiveboard / EditVisualization naming —
205+
// they're expected to be inert no-ops (`.on(undefined, ...)`) unless/until
206+
// those EmbedEvent members actually get added.
207+
liveboardEmbed.on(EmbedEvent.Edit, (payload) => {
208+
console.log('EmbedEvent.Edit', payload);
209+
logEvent('EmbedEvent.Edit', payload);
210+
});
211+
liveboardEmbed.on(EmbedEvent.EditLiveboard, (payload) => {
212+
console.log('EmbedEvent.EditLiveboard', payload);
213+
logEvent('EmbedEvent.EditLiveboard', payload);
214+
});
215+
liveboardEmbed.on(EmbedEvent.EditVisualization, (payload) => {
216+
console.log('EmbedEvent.EditVisualization', payload);
217+
logEvent('EmbedEvent.EditVisualization', payload);
218+
});
219+
liveboardEmbed.on(EmbedEvent.ALL, (payload: any) => {
220+
if (!allEventsCheckbox.checked) return;
221+
logEvent(`EmbedEvent.ALL \u2192 ${payload?.type ?? 'unknown'}`, payload);
222+
});
223+
liveboardEmbed.render();
224+
}
225+
226+
const configBar = document.createElement('div');
227+
configBar.style.display = 'flex';
228+
configBar.style.gap = '8px';
229+
configBar.style.alignItems = 'center';
230+
configBar.style.padding = '8px';
231+
document.body.insertBefore(configBar, app);
232+
233+
const configLabel = document.createElement('label');
234+
configLabel.textContent = 'Action config: ';
235+
configBar.appendChild(configLabel);
236+
237+
const configSelect = document.createElement('select');
238+
Object.keys(editActionConfigs).forEach((name) => {
239+
const option = document.createElement('option');
240+
option.value = name;
241+
option.textContent = name;
242+
configSelect.appendChild(option);
243+
});
244+
configSelect.onchange = () => {
245+
renderLiveboard(editActionConfigs[configSelect.value]);
246+
};
247+
configBar.appendChild(configSelect);
248+
249+
const addToggle = (label: string, initial: boolean, onToggle: (checked: boolean) => void) => {
250+
const toggleLabel = document.createElement('label');
251+
const checkbox = document.createElement('input');
252+
checkbox.type = 'checkbox';
253+
checkbox.checked = initial;
254+
checkbox.onchange = () => {
255+
onToggle(checkbox.checked);
256+
renderLiveboard(editActionConfigs[configSelect.value]);
257+
};
258+
toggleLabel.appendChild(checkbox);
259+
toggleLabel.appendChild(document.createTextNode(` ${label}`));
260+
configBar.appendChild(toggleLabel);
261+
};
262+
263+
addToggle('isLiveboardHeaderV2Enabled', isLiveboardHeaderV2Enabled, (checked) => {
264+
isLiveboardHeaderV2Enabled = checked;
265+
});
266+
addToggle('showLiveboardTitle', showLiveboardTitle, (checked) => {
267+
showLiveboardTitle = checked;
268+
});
269+
addToggle('isLiveboardMasterpiecesEnabled', isLiveboardMasterpiecesEnabled, (checked) => {
270+
isLiveboardMasterpiecesEnabled = checked;
271+
});
272+
addToggle('isLiveboardCompactHeaderEnabled', isLiveboardCompactHeaderEnabled, (checked) => {
273+
isLiveboardCompactHeaderEnabled = checked;
274+
});
275+
276+
renderLiveboard(editActionConfigs[configSelect.value]);
277+
278+
// TODO(debug): remove — buttons to test HostEvent.Edit for the normal
279+
// (Liveboard-level), explicit Liveboard-context, and viz-scoped variants.
280+
// There's no HostEvent.EditLiveboard / HostEvent.EditVisualization — same
281+
// HostEvent.Edit, differentiated by the payload/context args.
282+
283+
const buttonBar = document.createElement('div');
284+
buttonBar.style.display = 'flex';
285+
buttonBar.style.gap = '8px';
286+
buttonBar.style.padding = '8px';
287+
document.body.insertBefore(buttonBar, app);
288+
289+
const addTriggerButton = (label: string, onClick: () => void) => {
290+
const button = document.createElement('button');
291+
button.textContent = label;
292+
button.onclick = onClick;
293+
buttonBar.appendChild(button);
294+
};
295+
296+
addTriggerButton('Trigger Edit (normal)', () => {
297+
liveboardEmbed.trigger(HostEvent.Edit);
298+
});
299+
300+
addTriggerButton('Trigger Edit Liveboard Action', () => {
301+
liveboardEmbed.trigger(HostEvent.EditLiveboard, {});
302+
});
303+
304+
addTriggerButton('Trigger Edit Visualization', () => {
305+
if (!testVizId) {
306+
console.warn('[debug] set testVizId to a viz GUID on this Liveboard first');
307+
return;
308+
}
309+
liveboardEmbed.trigger(HostEvent.Edit, { vizId: testVizId });
310+
});
Lines changed: 29 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
width: 100%;
1919
}
2020
</style>
21-
<script type="module" crossorigin src="/assets/main-Dgo-o37A.js"></script>
21+
<script type="module" crossorigin src="/assets/main-Ck556jEI.js"></script>
2222
</head>
2323
<body>
2424
<div id="app"></div>

0 commit comments

Comments
 (0)