Skip to content

Commit 85cfd9e

Browse files
committed
feat: add sql metadata output renderer
1 parent 5c03793 commit 85cfd9e

File tree

4 files changed

+156
-0
lines changed

4 files changed

+156
-0
lines changed

build/esbuild/build.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,18 @@ async function buildAll() {
336336
path.join(extensionFolder, 'dist', 'webviews', 'webview-side', 'vegaRenderer', 'vegaRenderer.js'),
337337
{ target: 'web', watch: isWatchMode }
338338
),
339+
build(
340+
path.join(extensionFolder, 'src', 'webviews', 'webview-side', 'sql-metadata-renderer', 'index.ts'),
341+
path.join(
342+
extensionFolder,
343+
'dist',
344+
'webviews',
345+
'webview-side',
346+
'sqlMetadataRenderer',
347+
'sqlMetadataRenderer.js'
348+
),
349+
{ target: 'web', watch: isWatchMode }
350+
),
339351
build(
340352
path.join(extensionFolder, 'src', 'webviews', 'webview-side', 'variable-view', 'index.tsx'),
341353
path.join(extensionFolder, 'dist', 'webviews', 'webview-side', 'viewers', 'variableView.js'),

package.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,6 +1856,15 @@
18561856
"application/vnd.vega.v5+json"
18571857
],
18581858
"requiresMessaging": "optional"
1859+
},
1860+
{
1861+
"id": "deepnote-sql-metadata-renderer",
1862+
"displayName": "Deepnote SQL Metadata Renderer",
1863+
"entrypoint": "./dist/webviews/webview-side/sqlMetadataRenderer/sqlMetadataRenderer.js",
1864+
"mimeTypes": [
1865+
"application/vnd.deepnote.sql-output-metadata+json"
1866+
],
1867+
"requiresMessaging": "optional"
18591868
}
18601869
],
18611870
"viewsContainers": {
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import React, { memo } from 'react';
2+
3+
export interface SqlMetadataRendererProps {
4+
data: {
5+
cache_created_at?: string;
6+
compiled_query?: string;
7+
integration_id?: string;
8+
size_in_bytes?: number;
9+
status: string;
10+
variable_type?: string;
11+
};
12+
}
13+
14+
export const SqlMetadataRenderer = memo(function SqlMetadataRenderer({ data }: SqlMetadataRendererProps) {
15+
const getStatusMessage = () => {
16+
switch (data.status) {
17+
case 'read_from_cache_success':
18+
return {
19+
icon: '✓',
20+
text: 'Query result loaded from cache',
21+
color: 'var(--vscode-testing-iconPassed)'
22+
};
23+
case 'success_no_cache':
24+
return {
25+
icon: 'ℹ',
26+
text: 'Query executed successfully',
27+
color: 'var(--vscode-notificationsInfoIcon-foreground)'
28+
};
29+
case 'cache_not_supported_for_query':
30+
return {
31+
icon: 'ℹ',
32+
text: 'Caching not supported for this query type',
33+
color: 'var(--vscode-notificationsInfoIcon-foreground)'
34+
};
35+
default:
36+
return {
37+
icon: 'ℹ',
38+
text: `Status: ${data.status}`,
39+
color: 'var(--vscode-foreground)'
40+
};
41+
}
42+
};
43+
44+
const statusInfo = getStatusMessage();
45+
46+
const formatBytes = (bytes: number) => {
47+
if (bytes < 1024) {
48+
return `${bytes} B`;
49+
}
50+
if (bytes < 1024 * 1024) {
51+
return `${(bytes / 1024).toFixed(2)} KB`;
52+
}
53+
if (bytes < 1024 * 1024 * 1024) {
54+
return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
55+
}
56+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
57+
};
58+
59+
return (
60+
<div
61+
style={{
62+
padding: '8px 12px',
63+
margin: '4px 0',
64+
borderLeft: `3px solid ${statusInfo.color}`,
65+
backgroundColor: 'var(--vscode-textBlockQuote-background)',
66+
fontSize: '12px',
67+
fontFamily: 'var(--vscode-font-family)',
68+
color: 'var(--vscode-foreground)'
69+
}}
70+
>
71+
<div
72+
style={{
73+
display: 'flex',
74+
alignItems: 'center',
75+
gap: '8px',
76+
marginBottom: data.cache_created_at || data.size_in_bytes ? '6px' : '0'
77+
}}
78+
>
79+
<span style={{ color: statusInfo.color, fontSize: '14px', fontWeight: 'bold' }}>{statusInfo.icon}</span>
80+
<span style={{ fontWeight: 500 }}>{statusInfo.text}</span>
81+
</div>
82+
83+
{data.cache_created_at && (
84+
<div style={{ marginLeft: '22px', opacity: 0.8, fontSize: '11px' }}>
85+
Cache created: {new Date(data.cache_created_at).toLocaleString()}
86+
</div>
87+
)}
88+
89+
{data.size_in_bytes !== undefined && (
90+
<div style={{ marginLeft: '22px', opacity: 0.8, fontSize: '11px' }}>
91+
Result size: {formatBytes(data.size_in_bytes)}
92+
</div>
93+
)}
94+
</div>
95+
);
96+
});
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import type { ActivationFunction, OutputItem, RendererContext } from 'vscode-notebook-renderer';
2+
import * as React from 'react';
3+
import * as ReactDOM from 'react-dom';
4+
5+
import { SqlMetadataRenderer } from './SqlMetadataRenderer';
6+
7+
/**
8+
* Renderer for SQL metadata output (application/vnd.deepnote.sql-output-metadata+json).
9+
* This renderer displays information about SQL query execution, including cache status,
10+
* query size, and other metadata.
11+
*/
12+
export const activate: ActivationFunction = (_context: RendererContext<unknown>) => {
13+
return {
14+
renderOutputItem(outputItem: OutputItem, element: HTMLElement) {
15+
console.log(`SQL metadata renderer - rendering output item: ${outputItem.id}`);
16+
try {
17+
const data = outputItem.json();
18+
19+
console.log(`SQL metadata renderer - received data:`, data);
20+
21+
const root = document.createElement('div');
22+
element.appendChild(root);
23+
24+
ReactDOM.render(React.createElement(SqlMetadataRenderer, { data }), root);
25+
} catch (error) {
26+
console.error(`Error rendering SQL metadata: ${error}`);
27+
const errorDiv = document.createElement('div');
28+
errorDiv.style.padding = '10px';
29+
errorDiv.style.color = 'var(--vscode-errorForeground)';
30+
errorDiv.textContent = `Error rendering SQL metadata: ${error}`;
31+
element.appendChild(errorDiv);
32+
}
33+
},
34+
35+
disposeOutputItem(_id?: string) {
36+
// Cleanup if needed
37+
}
38+
};
39+
};

0 commit comments

Comments
 (0)