feat: Tradingview Lightweight Charts - #1402
Conversation
… restore correctly.
Co-authored-by: Copilot <copilot@github.com>
# Conflicts: # package-lock.json # package.json # tests/app.d/tests.app
# Conflicts: # package-lock.json # tests/app.d/tests.app
*_series constructors and chart-level kwargs on per-type constructors were removed; compose via tvl.chart(...) instead. Fixes server startup crash in e2e docker container. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s them Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # tests/app.d/tests.app
Fix pre-existing lint errors that fail `npm run test:ci` (test:ci:lint): - Move @deephaven/dashboard-core-plugins from devDependencies to dependencies (imported by non-test source; import/no-extraneous-deps) - strict-boolean-expressions: explicit null/empty checks - no-shadow: rename shadowing pendingDs locals to pendingResample - no-param-reassign: house-style inline disables for intentional mutation - no-nested-ternary: hoist chart-type formatter selection to if/else - drop unused error/isLoading state value bindings - normalize isDownsampleSwap to a definite boolean - consistent-type-imports, no-empty-function, react/destructuring-assignment, jsx-props-no-spreading, max-classes-per-file, and prettier formatting Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove 6 of the 7 eslint-disable comments added when first fixing lint, addressing the root causes instead: - no-explicit-any: pendingDownsample is a public field; drop the `as any` - no-param-reassign (x2): mutate via array-index locals, not forEach params - jsx-props-no-spreading (x2): destructure and pass props explicitly in tests - max-classes-per-file: make MockResizeObserver a mock factory (one class left) The one remaining disable (react-hooks/exhaustive-deps on the DOM-derived useDHChartTheme memo) is kept intentionally — it matches the established convention in the ui plugin for memos that depend on non-scope DOM state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The tvl plugin lagged the rest of the repo (e.g. dashboard-core-plugins ^0.85.42, components ^1.2.0, plugin ^1.2.0). Bump the shared @deephaven/* deps to the versions the sibling plugins (pivot / pivot-builder / plotly- express) pin, which are already hoisted at the workspace root: - components ^1.22.1, dashboard ^1.24.0, dashboard-core-plugins ^1.24.0, jsapi-bootstrap ^1.23.0, log ^1.8.0, plugin ^1.24.0, redux ^1.23.0, utils ^1.10.0, jsapi-types ^1.0.0-dev0.39.6 This dedupes the previously-nested dashboard-core-plugins@0.85.x tree onto the root 1.24.0 install (removing ~167 stale packages). Verified: repo-wide tsc, full build, and test:ci (unit + lint) all pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cut the tradingview-lightweight plugin's eslint-disable comments from 72 to 4 by fixing the underlying issues instead of suppressing them: Production source: - no-explicit-any (33): use real @deephaven/jsapi-types / lightweight-charts types (Widget.sendMessage, PartitionedTable, plot.Downsample, DateWrapper, Event<T>, IRange/LogicalRange), access now-public model fields directly, and add a declaration.d.ts for the `*.css?inline` import (drops @ts-ignore) - no-param-reassign (2): resolve colors into locals, not the params - no-continue (3): wrap loop bodies in positive conditions - no-non-null-assertion (1): get-or-create map entry - class-methods-use-this (1): make unwrapValue static - import/prefer-default-export (1): default-export the plugin Tests: - no-new (16): assign construction to a var + assert defined (house pattern) - no-underscore-dangle (9) + no-var-requires (1): expose mock internals under non-underscore names, import the same mock instance via `import * as` - no-explicit-any (2): `as never` / typed casts The 4 remaining are deliberate and match repo convention: react-hooks/ exhaustive-deps on two DOM-derived effects/memos (as the ui plugin does), and no-underscore-dangle on the intentional `__tvlTestHook` global debug hook. Verified: repo-wide tsc, build, and test:ci (unit + lint, 332 suites) all pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
ui docs preview (Available for 14 days) |
|
plotly-express docs preview (Available for 14 days) |
|
ui docs preview (Available for 14 days) |
|
plotly-express docs preview (Available for 14 days) |
|
ui docs preview (Available for 14 days) |
|
plotly-express docs preview (Available for 14 days) |
|
tradingview-lightweight docs preview (Available for 14 days) |
|
tradingview-lightweight docs preview (Available for 14 days) |
|
ui docs preview (Available for 14 days) |
|
plotly-express docs preview (Available for 14 days) |
|
tradingview-lightweight docs preview (Available for 14 days) |
|
ui docs preview (Available for 14 days) |
|
plotly-express docs preview (Available for 14 days) |
|
plotly-express docs preview (Available for 14 days) |
|
tradingview-lightweight docs preview (Available for 14 days) |
|
ui docs preview (Available for 14 days) |
There was a problem hiding this comment.
Pull request overview
Introduces the beta TradingView Lightweight Charts plugin, including Python APIs, JavaScript rendering, documentation, tests, and snapshot infrastructure.
Changes:
- Adds chart types, continuous time rendering, themes, tooltips, events, and downsampling.
- Adds Python, Jest, Playwright, and documentation coverage.
- Extends Docker-based documentation snapshot generation.
Reviewed changes
Copilot reviewed 54 out of 623 changed files in this pull request and generated 10 comments.
Show a summary per file
| File(s) | Description |
|---|---|
plugins/tradingview-lightweight/** |
New plugin implementation, packaging, tests, fixtures, docs, and snapshots. |
tools/image-snapshotter/** |
New chart-image snapshot generation and validation tooling. |
tests/** |
Adds TVL fixtures and stabilizes visual tests. |
plugins/ui/.../useDebouncedOnChange* |
Prevents callback replacement from dropping pending changes. |
sphinx_ext/deephaven_autodoc.py |
Handles raises sections and MDX brace escaping. |
docker-compose.docs*.yml, docker/python*/** |
Integrates TVL into documentation containers. |
tools/run_docker.sh, package.json |
Updates snapshot orchestration and diagnostics. |
.github/actions/get-changes/action.yml |
Adds TVL change detection. |
.gitignore |
Adds Python artifact exclusions. |
Suppressed comments (3)
plugins/tradingview-lightweight/README.md:38
chart()deliberately hard-broke these flat kwargs. The runnable example must use the groupedcrosshairandtime_scaleobjects or it raisesTypeError.
plugins/tradingview-lightweight/docs/README.md:60- This terminology entry repeats the nonexistent
pane_indexparameter; the constructors select a pane withpane=.
plugins/tradingview-lightweight/README.md:134 plugin_builder.pyhas no--pluginoption; plugins are positional arguments, and starting the separate server requires--server. This documented local workflow exits with an unknown-option error.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| tooltip_visible=True, | ||
| tooltip_value_precision=2, |
| # Simple candlestick chart | ||
| chart = tvl.candlestick( | ||
| ohlc_table, | ||
| time="Timestamp", |
| ```python order=my_chart | ||
| from deephaven.plot import tradingview_lightweight as tvl | ||
| t = tvl.data.values() | ||
| my_chart = tvl.line(t, time="Timestamp", value="Value") |
| - **Live Table Support**: Direct integration with real-time Deephaven tables, so charts update as the underlying data ticks. | ||
| - **Viewport-Aware Downsampling**: Pixel-accurate, whitespace-based downsampling that keeps panning and zooming smooth on multi-million-row series. | ||
| - **Server-Side Autobinning**: Histograms compute bin widths and counts directly in the Deephaven query engine, avoiding round-trips of raw data. | ||
| - **Multi-Pane Stacks**: Price, volume, and indicator series can be stacked into separate panes with independent height ratios via `pane_index`. |
| setupFilesAfterEach: [ | ||
| ...(baseConfig.setupFilesAfterEach ?? []), | ||
| path.join(__dirname, 'jest.setup.ts'), | ||
| ], | ||
| setupFiles: [ | ||
| ...(baseConfig.setupFiles ?? []), | ||
| path.join(__dirname, 'jest.setup.ts'), | ||
| ], |
| cp -rf "$PLUGIN_ROOT/src/js/dist/." "$DEST"/ | ||
| echo "[e2e] synced freshly built JS bundle into the installed package" |
| "update-dh-packages:ui": "npm run update-dh-packages -- --scope=@deephaven/js-plugin-ui --", | ||
| "validate-marketplace": "node tools/validate-marketplace.mjs", | ||
| "update-doc-snapshots": "./tools/run_docker.sh ./docker-compose.docs-snapshots.yml deephaven-plugins-docs-snapshotter", | ||
| "update-doc-snapshots": "docker compose -f ./docker/python/docker-compose.yml build server && (./tools/run_docker.sh ./docker-compose.docs-snapshots.yml deephaven-plugins-docs-image-snapshotter-tvl; ec=$?; ./tools/run_docker.sh ./docker-compose.docs-snapshots.yml deephaven-plugins-docs-error-reporter || true; exit $ec)", |
| if ! node /work/dist/validate-assets-cli.js "${SNAPSHOTS_HOST_DIR}"; then | ||
| VALIDATE_EXIT=$? | ||
| echo "[entrypoint] snapshot asset validation failed (exit ${VALIDATE_EXIT})." >&2 | ||
| # Prefer reporting the playwright failure if there was one, otherwise | ||
| # surface the validator's exit code. | ||
| if [ "${PLAYWRIGHT_EXIT}" = "0" ]; then | ||
| exit "${VALIDATE_EXIT}" | ||
| fi | ||
| fi |
| let raw: string; | ||
| try { | ||
| raw = readFileSync(full, 'utf8'); | ||
| } catch { | ||
| continue; | ||
| } | ||
| let parsed: { objects?: Record<string, ObjEntry> }; | ||
| try { | ||
| parsed = JSON.parse(raw); | ||
| } catch { | ||
| continue; | ||
| } |
|
|
||
| ### Build the docs locally | ||
|
|
||
| From the repo root: |
A record of most changes I made on top of Don's work is in
plans/DH-1376-tradingview-lightweight-review.mdI also added a
continuousargument (defaultTrue) to charts. Generally, this means data gaps aren't erased by default. This will make it so histograms are truly bar-to-bar, for a specific example. Setting toFalseswitches back to the default ordinal rendering mode for those desiring it.Since it is impossible to pin down everything without taking significant developer effort, I think our best bet is noting this as a beta plugin. If further work is highly desirable once initially surfaced we can dedicate more resources.