Skip to content

Commit 35355c3

Browse files
committed
feat(charts): Add visualization blocks support
1 parent 8386006 commit 35355c3

File tree

11 files changed

+2648
-90
lines changed

11 files changed

+2648
-90
lines changed

build/esbuild/build.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,11 @@ async function buildAll() {
329329
path.join(extensionFolder, 'dist', 'webviews', 'webview-side', 'dataframeRenderer', 'dataframeRenderer.js'),
330330
{ target: 'web', watch: isWatchMode }
331331
),
332+
build(
333+
path.join(extensionFolder, 'src', 'webviews', 'webview-side', 'vega-renderer', 'index.ts'),
334+
path.join(extensionFolder, 'dist', 'webviews', 'webview-side', 'vegaRenderer', 'vegaRenderer.js'),
335+
{ target: 'web', watch: isWatchMode }
336+
),
332337
build(
333338
path.join(extensionFolder, 'src', 'webviews', 'webview-side', 'variable-view', 'index.tsx'),
334339
path.join(extensionFolder, 'dist', 'webviews', 'webview-side', 'viewers', 'variableView.js'),

package-lock.json

Lines changed: 1996 additions & 58 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1818,6 +1818,15 @@
18181818
"application/vnd.deepnote.dataframe.v3+json"
18191819
],
18201820
"requiresMessaging": "optional"
1821+
},
1822+
{
1823+
"id": "deepnote-vega-renderer",
1824+
"displayName": "Deepnote Vega Chart Renderer",
1825+
"entrypoint": "./dist/webviews/webview-side/vegaRenderer/vegaRenderer.js",
1826+
"mimeTypes": [
1827+
"application/vnd.vega.v5+json"
1828+
],
1829+
"requiresMessaging": "optional"
18211830
}
18221831
],
18231832
"viewsContainers": {
@@ -2126,6 +2135,7 @@
21262135
"bootstrap": "^5.0.0",
21272136
"bootstrap-less": "^3.3.8",
21282137
"cross-fetch": "^3.1.5",
2138+
"d3-format": "^3.1.0",
21292139
"encoding": "^0.1.13",
21302140
"fast-deep-equal": "^2.0.1",
21312141
"format-util": "^1.0.5",
@@ -2151,6 +2161,7 @@
21512161
"react-redux": "^7.1.1",
21522162
"react-svg-pan-zoom": "3.9.0",
21532163
"react-svgmt": "1.1.11",
2164+
"react-vega": "^7.7.1",
21542165
"react-virtualized": "^9.21.1",
21552166
"redux": "^4.0.4",
21562167
"redux-logger": "^3.0.6",
@@ -2166,6 +2177,7 @@
21662177
"tcp-port-used": "^1.0.1",
21672178
"tmp": "^0.2.4",
21682179
"url-parse": "^1.5.10",
2180+
"vega-embed": "^7.1.0",
21692181
"vscode-debugprotocol": "^1.41.0",
21702182
"vscode-languageclient": "8.0.2-next.5",
21712183
"vscode-tas-client": "^0.1.84",
@@ -2186,6 +2198,7 @@
21862198
"@types/chai-arrays": "^2.0.1",
21872199
"@types/chai-as-promised": "^7.1.6",
21882200
"@types/cors": "^2.8.6",
2201+
"@types/d3-format": "^3.0.4",
21892202
"@types/debug": "^4.1.5",
21902203
"@types/dedent": "^0.7.0",
21912204
"@types/del": "^4.0.0",

src/kernels/execution/cellExecution.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ import { KernelError } from '../errors/kernelError';
3232
import { getCachedSysPrefix } from '../../platform/interpreter/helpers';
3333
import { getCellMetadata } from '../../platform/common/utils';
3434
import { NotebookCellExecutionState, notebookCellExecutions } from '../../platform/notebooks/cellExecutionStateService';
35-
import { createBlockFromPocket } from '../../notebooks/deepnote/pocket';
3635
import { createPythonCode } from '@deepnote/blocks';
36+
import { DeepnoteDataConverter } from '../../notebooks/deepnote/deepnoteDataConverter';
3737

3838
/**
3939
* Factory for CellExecution objects.
@@ -416,10 +416,11 @@ export class CellExecution implements ICellExecution, IDisposable {
416416
metadata: this.cell.metadata,
417417
outputs: [...(this.cell.outputs || [])]
418418
};
419-
const deepnoteBlock = createBlockFromPocket(cellData, this.cell.index);
420419

421-
// Use createPythonCode to generate code with table state already included
422-
logger.info(`Cell ${this.cell.index}: Using createPythonCode to generate execution code with table state`);
420+
const dataConverter = new DeepnoteDataConverter();
421+
const deepnoteBlock = dataConverter.convertCellToBlock(cellData, this.cell.index);
422+
423+
logger.info(`Cell ${this.cell.index}: Using createPythonCode for ${deepnoteBlock.type} block`);
423424
code = createPythonCode(deepnoteBlock);
424425

425426
// Generate metadata from our cell (some kernels expect this.)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { NotebookCellData, NotebookCellKind } from 'vscode';
2+
3+
import type { BlockConverter } from './blockConverter';
4+
import type { DeepnoteBlock } from '../deepnoteTypes';
5+
6+
/**
7+
* Converter for Deepnote visualization blocks (chart blocks).
8+
* Displays blocks as editable JSON with variable name, spec, and filters.
9+
* The JSON is converted to Python code at execution time.
10+
*/
11+
export class VisualizationBlockConverter implements BlockConverter {
12+
applyChangesToBlock(block: DeepnoteBlock, cell: NotebookCellData): void {
13+
block.content = '';
14+
15+
// Parse the JSON from the cell to update metadata
16+
try {
17+
const config = JSON.parse(cell.value || '{}');
18+
19+
if (!block.metadata) {
20+
block.metadata = {};
21+
}
22+
23+
if (config.variable) {
24+
block.metadata.deepnote_variable_name = config.variable;
25+
}
26+
27+
if (config.spec) {
28+
block.metadata.deepnote_visualization_spec = config.spec;
29+
}
30+
31+
if (config.filters) {
32+
if (!block.metadata.deepnote_chart_filter) {
33+
block.metadata.deepnote_chart_filter = {};
34+
}
35+
block.metadata.deepnote_chart_filter.advancedFilters = config.filters;
36+
}
37+
} catch (error) {
38+
// If JSON parsing fails, leave metadata unchanged
39+
console.warn('Failed to parse visualization JSON:', error);
40+
}
41+
}
42+
43+
canConvert(blockType: string): boolean {
44+
return blockType.toLowerCase() === 'visualization';
45+
}
46+
47+
convertToCell(block: DeepnoteBlock): NotebookCellData {
48+
const variableName = (block.metadata as any)?.deepnote_variable_name || 'df';
49+
const spec = (block.metadata as any)?.deepnote_visualization_spec || {};
50+
const filters = (block.metadata as any)?.deepnote_chart_filter?.advancedFilters || [];
51+
52+
// Create a clean JSON representation that users can edit
53+
const config = {
54+
variable: variableName,
55+
spec: spec,
56+
filters: filters
57+
};
58+
59+
const jsonContent = JSON.stringify(config, null, 2);
60+
const cell = new NotebookCellData(NotebookCellKind.Code, jsonContent, 'python');
61+
62+
return cell;
63+
}
64+
65+
getSupportedTypes(): string[] {
66+
return ['visualization'];
67+
}
68+
}

0 commit comments

Comments
 (0)