Skip to content

Commit

Permalink
[feat] Hubble gl integration (#1899)
Browse files Browse the repository at this point in the history
  • Loading branch information
igorDykhta committed Aug 8, 2022
1 parent d31fe64 commit 6c51a2a
Show file tree
Hide file tree
Showing 17 changed files with 414 additions and 263 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -23,6 +23,7 @@ package-lock.json
/index.html

npm-debug.log
.history/

.pnp.*
.yarn/*
Expand Down
1 change: 1 addition & 0 deletions examples/demo-app/package.json
Expand Up @@ -7,6 +7,7 @@
"start-local-deck": "webpack-dev-server --mode development --env.es6 --env.deck --progress --hot --open",
"start-local-deck-src": "webpack-dev-server --mode development --env.es6 --env.deck_src --progress --hot --open",
"start-local-loaders-src": "webpack-dev-server --mode development --env.es6 --env.loaders_src --progress --hot --open",
"start-local-hubble-src": "webpack-dev-server --mode development --env.es6 --env.hubble_src --progress --hot --open",
"start-local-https": "webpack-dev-server --mode development --https --env.es6 --progress --hot --open"
},
"dependencies": {
Expand Down
32 changes: 24 additions & 8 deletions examples/webpack.config.local.js
Expand Up @@ -45,6 +45,9 @@ const EXTERNAL_DECK_SRC = resolve(__dirname, '../../deck.gl');
// For debugging loaders.gl, load loaders.gl from external loaders.gl directory
const EXTERNAL_LOADERS_SRC = resolve(__dirname, '../../loaders.gl');

// For debugging hubble.gl, load hubble.gl from external hubble.gl directory
const EXTERNAL_HUBBLE_SRC = resolve(__dirname, '../../hubble.gl');

// Support for hot reloading changes to the deck.gl library:
function makeLocalDevConfig(env, EXAMPLE_DIR = LIB_DIR, externals = {}) {
const resolveAlias = {
Expand All @@ -57,26 +60,30 @@ function makeLocalDevConfig(env, EXAMPLE_DIR = LIB_DIR, externals = {}) {
'react-intl': `${NODE_MODULES_DIR}/react-intl`
};

// Combine flags
const useLocalDeck = env.deck || env.hubble_src;
const useRepoDeck = env.deck_src;

// resolve deck.gl from local dir
if (env.deck || env.deck_src) {
if (useLocalDeck || useRepoDeck) {
// Load deck.gl from root node_modules
// if env.deck_src Load deck.gl from deck.gl/modules/main/src folder parallel to kepler.gl
resolveAlias['deck.gl'] = env.deck
resolveAlias['deck.gl'] = useLocalDeck
? `${NODE_MODULES_DIR}/deck.gl/src`
: `${EXTERNAL_DECK_SRC}/modules/main/src`;

// if env.deck Load @deck.gl modules from root node_modules/@deck.gl
// if env.deck_src Load @deck.gl modules from deck.gl/modules folder parallel to kepler.gl
externals['deck.gl'].forEach(mdl => {
resolveAlias[`@deck.gl/${mdl}`] = env.deck
resolveAlias[`@deck.gl/${mdl}`] = useLocalDeck
? `${NODE_MODULES_DIR}/@deck.gl/${mdl}/src`
: `${EXTERNAL_DECK_SRC}/modules/${mdl}/src`;
});

['luma.gl', 'probe.gl', 'loaders.gl'].forEach(name => {
// if env.deck Load ${name} from root node_modules
// if env.deck_src Load ${name} from deck.gl/node_modules folder parallel to kepler.gl
resolveAlias[name] = env.deck
resolveAlias[name] = useLocalDeck
? `${NODE_MODULES_DIR}/${name}/src`
: name === 'probe.gl'
? `${EXTERNAL_DECK_SRC}/node_modules/${name}/src`
Expand All @@ -85,7 +92,7 @@ function makeLocalDevConfig(env, EXAMPLE_DIR = LIB_DIR, externals = {}) {
// if env.deck Load @${name} modules from root node_modules/@${name}
// if env.deck_src Load @${name} modules from deck.gl/node_modules/@${name} folder parallel to kepler.gl`
externals[name].forEach(mdl => {
resolveAlias[`@${name}/${mdl}`] = env.deck
resolveAlias[`@${name}/${mdl}`] = useLocalDeck
? `${NODE_MODULES_DIR}/@${name}/${mdl}/src`
: `${EXTERNAL_DECK_SRC}/node_modules/@${name}/${mdl}/src`;
});
Expand All @@ -98,6 +105,12 @@ function makeLocalDevConfig(env, EXAMPLE_DIR = LIB_DIR, externals = {}) {
});
}

if (env.hubble_src) {
externals['hubble.gl'].forEach(mdl => {
resolveAlias[`@hubble.gl/${mdl}`] = `${EXTERNAL_HUBBLE_SRC}/modules/${mdl}/src`;
});
}

logStep(`resolve.alias:\n ${JSON.stringify(resolveAlias, null, 2)}`);

// load deck.gl from
Expand Down Expand Up @@ -157,6 +170,7 @@ function makeBabelRule(env, exampleDir) {
join(EXTERNAL_DECK_SRC, 'node_modules/@loaders.gl')
]
: []),
...(env.hubble_src ? [join(EXTERNAL_HUBBLE_SRC, 'modules')] : []),
join(exampleDir, 'src'),
SRC_DIR
],
Expand All @@ -172,6 +186,7 @@ function makeBabelRule(env, exampleDir) {
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-optional-chaining',
'@babel/plugin-proposal-export-namespace-from',
'@babel/plugin-transform-runtime',
[
'search-and-replace',
{
Expand Down Expand Up @@ -232,8 +247,8 @@ function addBabelSettings(env, config, exampleDir) {
}

module.exports = (exampleConfig, exampleDir) => env => {
// find all @deck.gl @luma.gl @loaders.gl modules
const modules = ['@deck.gl', '@loaders.gl', '@luma.gl', '@probe.gl'];
// find all @deck.gl @luma.gl @loaders.gl @hubble.gl modules
const modules = ['@deck.gl', '@loaders.gl', '@luma.gl', '@probe.gl', '@hubble.gl'];
const loadAllDirs = modules.map(
dir =>
new Promise(function readDir(success, reject) {
Expand All @@ -252,7 +267,8 @@ module.exports = (exampleConfig, exampleDir) => env => {
'deck.gl': results[0],
'loaders.gl': results[1],
'luma.gl': results[2],
'probe.gl': results[3]
'probe.gl': results[3],
'hubble.gl': results[4]
}))
.then(externals => {
const config = addLocalDevSettings(env, exampleConfig, exampleDir, externals);
Expand Down
3 changes: 3 additions & 0 deletions src/actions/action-types.ts
Expand Up @@ -152,6 +152,9 @@ const ActionTypes = {
SET_EXPORT_IMAGE_ERROR: `${ACTION_PREFIX}SET_EXPORT_IMAGE_ERROR`,
CLEANUP_EXPORT_IMAGE: `${ACTION_PREFIX}CLEANUP_EXPORT_IMAGE`,

// uiState > export video (state only, via hubble.gl)
SET_EXPORT_VIDEO_SETTING: `${ACTION_PREFIX}SET_EXPORT_VIDEO_SETTING`,

// uiState > export data
SET_EXPORT_SELECTED_DATASET: `${ACTION_PREFIX}SET_EXPORT_SELECTED_DATASET`,
SET_EXPORT_DATA_TYPE: `${ACTION_PREFIX}SET_EXPORT_DATA_TYPE`,
Expand Down
@@ -0,0 +1,68 @@
import React, {useCallback} from 'react';
import {FormattedMessage} from 'localization';
import {ReactComponentLike} from 'prop-types';
import IconButton from '../icon-button';
import {Tooltip} from 'components/common/styled-components';

export interface AnimationItem {
id: string;
icon: ReactComponentLike;
tooltip: string;
}
interface AnimationWindowControlProps {
animationWindow?: string;
setFilterAnimationWindow: (id: string) => void;
toggleAnimationWindowControl: () => void;
height?: string;
animationItems: {[key: string]: AnimationItem};
btnStyle;
showAnimationWindowControl: boolean;
}

function AnimationWindowControlFactory(): React.FC<AnimationWindowControlProps> {
const AnimationWindowControl = ({
animationWindow,
setFilterAnimationWindow,
toggleAnimationWindowControl,
height,
animationItems,
btnStyle = {},
showAnimationWindowControl
}: AnimationWindowControlProps) => {
const onSelectAnimationControl = useCallback(
item => {
setFilterAnimationWindow(item.id);
toggleAnimationWindowControl();
},
[setFilterAnimationWindow, toggleAnimationWindowControl]
);

return showAnimationWindowControl ? (
<div className="animation-window-control">
{Object.values(animationItems)
.filter(item => item.id !== animationWindow)
.map(item => (
<IconButton
key={item.id}
data-tip
data-for={`${item.id}-tooltip`}
className="playback-control-button"
onClick={() => onSelectAnimationControl(item)}
{...btnStyle}
>
<item.icon height={height} />
{item.tooltip ? (
<Tooltip id={`${item.id}-tooltip`} effect="solid" place="top">
<FormattedMessage id={item.tooltip} />
</Tooltip>
) : null}
</IconButton>
))}
</div>
) : null;
};

return AnimationWindowControl;
}

export default AnimationWindowControlFactory;
44 changes: 44 additions & 0 deletions src/components/common/animation-control/play-control.tsx
@@ -0,0 +1,44 @@
import React from 'react';
import classnames from 'classnames';
import {FormattedMessage} from 'localization';
import {Tooltip} from 'components/common/styled-components';
import IconButton from '../icon-button';

const DELAY_SHOW = 500;

function PlayControlFactory() {
const PlayControl = ({
showAnimationWindowControl,
isAnimating,
pauseAnimation,
startAnimation,
isSpeedControlVisible,
btnStyle,
playbackIcons,
buttonHeight
}) => {
return showAnimationWindowControl ? null : (
<IconButton
data-tip
data-for="animate-play-pause"
className={classnames('playback-control-button', {active: isAnimating})}
onClick={isAnimating ? pauseAnimation : startAnimation}
hide={isSpeedControlVisible}
{...btnStyle}
>
{isAnimating ? (
<playbackIcons.pause height={buttonHeight} />
) : (
<playbackIcons.play height={buttonHeight} />
)}
<Tooltip id="animate-play-pause" place="top" delayShow={DELAY_SHOW} effect="solid">
<FormattedMessage id={isAnimating ? 'tooltip.pause' : 'tooltip.play'} />
</Tooltip>
</IconButton>
);
};

return PlayControl;
}

export default PlayControlFactory;

0 comments on commit 6c51a2a

Please sign in to comment.