Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build/features.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"mcp-apps": true
}
3,091 changes: 3,091 additions & 0 deletions build/index.js

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions build/index.js.map

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions build/telemetry/tracing.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions build/telemetry/tracing.js.map

Large diffs are not rendered by default.

81 changes: 81 additions & 0 deletions build/web/apps/dist/mcp-app.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion features.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"mcp-apps": false
"mcp-apps": true

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ Info · 🎨 Style

The mcp-apps feature flag is flipped to true in what appears to be a shared config file. If this is intended only for development/testing, shipping it enabled by default may unintentionally expose the feature.

Tip

Suggested fix

Confirm this flag change is intentional for production; if not, revert or gate behind an environment-specific mechanism.


Review by CodeNod

}
38 changes: 36 additions & 2 deletions src/web/apps/src/lib/embedTableauViz.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('createTableauVizElement', () => {
expect(element.tagName.toLowerCase()).toBe('tableau-viz');
expect(element.getAttribute('src')).toBe(vizUrl);
expect(element.getAttribute('token')).toBe(token);
expect(element.getAttribute('toolbar')).toBe('hidden');
});
});

Expand Down Expand Up @@ -107,12 +108,13 @@ describe('embedTableauViz', () => {

expect(vizElement).toBeTruthy();

// Simulate firstvizsizeknown event with viz height
// Simulate firstvizsizeknown event with viz dimensions
const event = new CustomEvent('firstvizsizeknown', {
detail: {
vizSize: {
sheetSize: {
maxSize: {
width: 1200,
height: 800,
},
},
Expand All @@ -122,10 +124,42 @@ describe('embedTableauViz', () => {

vizElement.dispatchEvent(event);

// Should set height to the reported viz height
// Should set height attribute and style for the Embedding API iframe sizing
expect(vizElement.getAttribute('height')).toBe('800');
expect(vizElement.style.height).toBe('800px');
});

it('should set width to 100% string to preserve responsive behavior', () => {
const vizUrl = 'https://prod-uswest-c.online.tableau.com/site/mysite/views/workbook/view';
const token = 'test-token-123';

embedTableauViz(vizUrl, token);

const container = document.getElementById('tableauVizContainer');
const vizElement = container?.querySelector('tableau-viz') as HTMLElement;

expect(vizElement).toBeTruthy();

// Simulate firstvizsizeknown event with viz dimensions
const event = new CustomEvent('firstvizsizeknown', {
detail: {
vizSize: {
sheetSize: {
maxSize: {
width: 1200,
height: 800,
},
},
},
},
});

vizElement.dispatchEvent(event);

// Width should be set to "100%" to maintain responsive behavior
expect(vizElement.getAttribute('width')).toBe('100%');
});

it('should leave height unset when firstvizsizeknown has no numeric height', () => {
const vizUrl = 'https://prod-uswest-c.online.tableau.com/site/mysite/views/workbook/view';
const token = 'test-token-123';
Expand Down
17 changes: 14 additions & 3 deletions src/web/apps/src/lib/embedTableauViz.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export function createTableauVizElement(vizUrl: string, token: string): HTMLElem
// Set the token for authentication
viz.setAttribute('token', token);

// Hide the toolbar to prevent inner scrollbar (toolbar adds ~27-40px beyond reported sheet height)
viz.setAttribute('toolbar', 'hidden');

return viz;
}

Expand All @@ -39,16 +42,24 @@ export function embedTableauViz(vizUrl: string, token: string): void {
const viz = createTableauVizElement(vizUrl, token);

// The Embedding API reports the viz's natural size via `firstvizsizeknown`.
// Set the element's height to the viz's natural sheet height so it renders
// fully; the ext-apps SDK's built-in auto-resize then grows the app frame to
// match the resulting document height.
// Set the element's width/height ATTRIBUTES (not just CSS) so the Embedding
// API sizes its internal cross-origin iframe correctly. Without attributes,
// the iframe uses a default size and creates its own scrollbar.
// Width is set to "100%" for responsive behavior; height is the native px value.
viz.addEventListener('firstvizsizeknown', (event) => {
const vizSize = (event as CustomEvent).detail?.vizSize;
const sheetHeight = vizSize?.sheetSize?.maxSize?.height;
if (typeof sheetHeight !== 'number') {
return;
}

console.log('height: ', sheetHeight);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ Info · 🧠 Logic

A console.log('height: ', sheetHeight) debug statement is left in production code. This will emit noise in the browser console for every viz load.

Tip

Suggested fix

Remove the console.log statement or replace it with a conditional debug-level log.


Review by CodeNod


// Set attributes for Embedding API iframe sizing
viz.setAttribute('width', '100%');
viz.setAttribute('height', String(sheetHeight));

// Also set CSS height for backward compatibility
viz.style.height = `${sheetHeight}px`;
});

Expand Down
Loading
Loading