Skip to content

Commit

Permalink
pydeck and @deck.gl/jupyter-widget: Add render test for custom layer …
Browse files Browse the repository at this point in the history
…loading (#4267)
  • Loading branch information
ajduberstein committed Feb 20, 2020
1 parent 89090a5 commit 4c98bd0
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 30 deletions.
38 changes: 25 additions & 13 deletions modules/jupyter-widget/src/create-deck.js
@@ -1,3 +1,4 @@
/* global window */
import makeTooltip from './widget-tooltip';

import mapboxgl from './ssr-safe-mapbox';
Expand All @@ -8,6 +9,8 @@ import {registerLoaders} from '@loaders.gl/core';

import * as deck from './deck-bundle';

import {loadScript, alreadyLoaded} from './script-utils';

import GL from '@luma.gl/constants';

function extractClasses(library) {
Expand Down Expand Up @@ -41,18 +44,6 @@ const jsonConverter = new deck.JSONConverter({
configuration: jsonConverterConfiguration
});

/* global document, window */
function loadScript(url) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
const head = document.querySelector('head');
head.appendChild(script);
return new Promise(resolve => {
script.onload = resolve;
});
}

function loadExternalLibrary({libraryName, resourceUri, onComplete}, loadResource = loadScript) {
// NOTE loadResource is for testing only
loadResource(resourceUri).then(res => {
Expand All @@ -65,16 +56,37 @@ function loadExternalLibrary({libraryName, resourceUri, onComplete}, loadResourc
});
}

function addCustomLibraries(customLibraries) {
if (!customLibraries) {
return;
}
for (const obj of customLibraries) {
// obj is an object of the form `{libraryName, resourceUri}`
if (!alreadyLoaded(obj.resourceUri)) {
loadExternalLibrary(obj);
}
}
}

function updateDeck(inputJson, deckgl) {
const results = jsonConverter.convert(inputJson);
deckgl.setProps(results);
}

function createDeck({mapboxApiKey, container, jsonInput, tooltip, handleClick, handleWarning}) {
function createDeck({
mapboxApiKey,
container,
jsonInput,
tooltip,
handleClick,
handleWarning,
customLibraries
}) {
let deckgl;
try {
const props = jsonConverter.convert(jsonInput);

addCustomLibraries(customLibraries);
const getTooltip = makeTooltip(tooltip);

deckgl = new deck.DeckGL({
Expand Down
24 changes: 24 additions & 0 deletions modules/jupyter-widget/src/script-utils.js
@@ -0,0 +1,24 @@
/* global document */

function alreadyLoaded(url) {
// Save time by not reloading the same URL
for (const scriptTag of document.querySelectorAll('script')) {
if (scriptTag.src === url) {
return true;
}
}
return false;
}

function loadScript(url) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
const head = document.querySelector('head');
head.appendChild(script);
return new Promise(resolve => {
script.onload = resolve;
});
}

export {loadScript, alreadyLoaded};
21 changes: 6 additions & 15 deletions modules/jupyter-widget/src/widget.js
Expand Up @@ -3,7 +3,7 @@ import {DOMWidgetModel, DOMWidgetView} from '@jupyter-widgets/base';

import {MODULE_NAME, MODULE_VERSION} from './version';

import {jsonConverter, createDeck, updateDeck, loadExternalLibrary} from './create-deck';
import {jsonConverter, createDeck, updateDeck} from './create-deck';
import {deserializeMatrix, processDataBuffer} from './binary-transport';

const MAPBOX_CSS_URL = 'https://api.tiles.mapbox.com/mapbox-gl-js/v1.2.1/mapbox-gl.css';
Expand Down Expand Up @@ -37,7 +37,7 @@ export class DeckGLModel extends DOMWidgetModel {
_view_name: DeckGLModel.view_name,
_view_module: DeckGLModel.view_module,
_view_module_version: DeckGLModel.view_module_version,
classes: [],
custom_libraries: [],
json_input: null,
mapbox_key: null,
selected_data: [],
Expand Down Expand Up @@ -81,6 +81,8 @@ export class DeckGLView extends DOMWidgetView {
initialize() {
this.listenTo(this.model, 'destroy', this.remove);

const customLibraries = this.model.get('custom_libraries');

const container = document.createElement('div');

this.el.appendChild(container);
Expand Down Expand Up @@ -109,7 +111,8 @@ export class DeckGLView extends DOMWidgetView {
jsonInput,
tooltip,
handleClick: this.handleClick.bind(this),
handleWarning: this.handleWarning.bind(this)
handleWarning: this.handleWarning.bind(this),
customLibraries
});
}

Expand All @@ -125,22 +128,10 @@ export class DeckGLView extends DOMWidgetView {

this.model.on('change:json_input', this.valueChanged.bind(this), this);
this.model.on('change:data_buffer', this.dataBufferChanged.bind(this), this);
this.model.on('change:classes', this.addNewCustomLayers.bind(this), this);

this.addNewCustomLayers();
this.dataBufferChanged();
}

addNewCustomLayers() {
const customLibraries = this.model.get('custom_libraries');
if (customLibraries) {
for (const obj of customLibraries) {
// obj is an object of the form `{libraryName, resourceUri}`
loadExternalLibrary(obj);
}
}
}

dataBufferChanged() {
if (this.model.get('data_buffer')) {
const propsWithBinary = processDataBuffer({
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions test/render/jupyter-widget-custom-layer-bundle.js

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

7 changes: 5 additions & 2 deletions test/render/jupyter-widget-test.html
Expand Up @@ -22,14 +22,17 @@
<script type="text/javascript" src="/modules/jupyter-widget/dist/index.js"></script>
<script type="text/javascript">
let deck;
const customLibraries = [{libraryName: 'CustomLayerLibrary', resourceUri: '/test/render/jupyter-widget-custom-layer-bundle.js'}];

window.onmessage = evt => {
if (!deck) {
deck = createDeck({
mapboxApiKey: 'NO_API_KEY',
container: document.getElementById('app'),
jsonInput: evt.data.json,
useTooltip: true
});
useTooltip: true,
customLibraries
});

deck.setProps({
onAfterRender: () => window.top.postMessage('done')
Expand Down
22 changes: 22 additions & 0 deletions test/render/jupyter-widget.js
Expand Up @@ -299,6 +299,28 @@ const TEST_CASES = [
]
},
goldenImage: './test/render/golden-images/jupyter-widget-failed-function.png'
},
{
name: 'CustomLayer',
json: {
description: 'Test of custom layer loading',
viewState: {
longitude: 0,
latitude: 0,
zoom: 4
},
layers: [
{
'@@type': 'DemoCompositeLayer',
data: [[0, 0], [2, 0], [0, 2], [2, 2], [3, 3], [4, 4]],
getPosition: '@@=-',
getLineColor: [0, 0, 0],
getFillColor: [20, 160, 0, 180],
getRadius: 1000000
}
]
},
goldenImage: './test/render/golden-images/jupyter-widget-custom-layer.png'
}
].filter(Boolean);

Expand Down

0 comments on commit 4c98bd0

Please sign in to comment.