diff --git a/bindings/python/pydeck/pydeck/bindings/view_state.py b/bindings/python/pydeck/pydeck/bindings/view_state.py index d3f33851313..cddd8eb4bc6 100644 --- a/bindings/python/pydeck/pydeck/bindings/view_state.py +++ b/bindings/python/pydeck/pydeck/bindings/view_state.py @@ -3,7 +3,8 @@ class ViewState(JSONMixin): """An object that represents where the state of a viewport, essentially where the screen is focused. - If you have two dimensional data and you don't want to set this manually, see :func:`pydeck.data_utils.viewport_helpers.compute_view`. + If you have two dimensional data and you don't want to set this manually, + see :func:`pydeck.data_utils.viewport_helpers.compute_view`. Parameters diff --git a/bindings/python/pydeck/pydeck/widget/widget.py b/bindings/python/pydeck/pydeck/widget/widget.py index 90094d2658c..7dad94b0399 100644 --- a/bindings/python/pydeck/pydeck/widget/widget.py +++ b/bindings/python/pydeck/pydeck/widget/widget.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import ipywidgets as widgets -from traitlets import Any, Int, Unicode +from traitlets import Any, Int, Unicode, observe from ._frontend import module_name, module_version @@ -30,8 +30,8 @@ class DeckGLWidget(widgets.DOMWidget): Data passed from Jupyter widget frontend back to Python backend tooltip : bool or dict of {str: str}, default True See the ``Deck`` constructor. - - + js_error : str, default None + JS console error, if any """ _model_name = Unicode('DeckGLModel').tag(sync=True) _model_module = Unicode(module_name).tag(sync=True) @@ -45,3 +45,8 @@ class DeckGLWidget(widgets.DOMWidget): width = Any('100%').tag(sync=True) selected_data = Any().tag(sync=True) tooltip = Any(True).tag(sync=True) + js_error = Unicode(None, allow_none=True).tag(sync=True) + + @observe('js_error') + def _observe_js_error(self, change): + widgets.append_stderr('JavaScript error detected: %s' % change['new']) diff --git a/modules/jupyter-widget/src/utils.js b/modules/jupyter-widget/src/utils.js index f93b409e8d5..81bce4fff2f 100644 --- a/modules/jupyter-widget/src/utils.js +++ b/modules/jupyter-widget/src/utils.js @@ -24,7 +24,18 @@ export function updateDeck(inputJSON, {jsonConverter, deckgl}) { deckgl.setProps(results); } -export function initDeck({mapboxApiKey, container, jsonInput, tooltip, onComplete, handleClick}) { +export function initDeck( + {mapboxApiKey, container, jsonInput, tooltip, onComplete, handleClick, handleError} = { + mapboxApiKey: null, + container: null, + jsonInput: null, + tooltip: null, + onComplete: null, + handleClick: null, + // eslint-disable-next-line + handleError: console.error + } +) { require(['mapbox-gl', 'h3', 's2Geometry'], mapboxgl => { require(['deck.gl', 'loaders.gl/csv'], (deck, loaders) => { try { @@ -61,7 +72,7 @@ export function initDeck({mapboxApiKey, container, jsonInput, tooltip, onComplet } catch (err) { // This will fail in node tests // eslint-disable-next-line - console.error(err); + handleError(err); } return {}; }); diff --git a/modules/jupyter-widget/src/widget.js b/modules/jupyter-widget/src/widget.js index e99c81fee6e..877d02b8fab 100644 --- a/modules/jupyter-widget/src/widget.js +++ b/modules/jupyter-widget/src/widget.js @@ -23,7 +23,8 @@ export class DeckGLModel extends DOMWidgetModel { selected_data: null, tooltip: null, width: '100%', - height: 500 + height: 500, + js_error: null }; } @@ -81,7 +82,8 @@ export class DeckGLView extends DOMWidgetView { onComplete: ({jsonConverter, deckgl}) => { this.jsonDeck = {jsonConverter, deckgl}; }, - handleClick: this.handleClick.bind(this) + handleClick: this.handleClick.bind(this), + handleError: this.handleError }); } @@ -114,4 +116,12 @@ export class DeckGLView extends DOMWidgetView { } this.model.save_changes(); } + + handleError(err) { + if (!err) { + return; + } + this.model.set('js_error', err); + this.model.save_changes(); + } }