Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Chore]: Technical: Translate root components to typescript #1790

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"start:e2e": "npm run install-and-start -- examples/demo-app start-local-e2e",
"build": "rm -fr dist && babel src --out-dir dist --source-maps inline --extensions '.ts,.tsx,.js,.jsx' --ignore '**/*.d.ts'",
"build:umd": "webpack --config ./webpack/umd.js --progress --env.prod",
"build:types": "webpack --config ./webpack/build_types.js --progress",
"build:types": "tsc --project tsconfig.production.json",
"analyze": "npm run analyze:bundle",
"analyze:bundle": "webpack --config ./webpack/bundle.js --progress --env.prod",
"check-licence": "uber-licence --dry",
Expand Down Expand Up @@ -111,9 +111,12 @@
"@types/lodash.get": "^4.4.6",
"@types/lodash.isequal": "^4.5.5",
"@types/lodash.pick": "^4.4.6",
"@types/mapbox__geo-viewport": "^0.4.1",
"@types/react-lifecycles-compat": "^3.0.1",
"@types/react-map-gl": "^6.1.2",
"@types/react-modal": "^3.13.1",
"@types/react-onclickoutside": "^6.7.4",
"@types/react-redux": "^7.1.23",
"@types/react-virtualized": "^9.21.20",
"@types/react-vis": "^1.8.0",
"classnames": "^2.2.1",
Expand Down
55 changes: 45 additions & 10 deletions src/components/bottom-widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,17 @@ import AnimationControllerFactory from './common/animation-control/animation-con
import {ANIMATION_WINDOW, DIMENSIONS, FILTER_TYPES} from 'constants/default-settings';
import {getIntervalBins} from 'utils/filter-utils';
import {media} from 'styles/media-breakpoints';
import {AnimationConfig, TimeRangeFilter} from 'reducers';
import {bottomWidgetSelector} from './kepler-gl';

const maxWidth = 1080;

const BottomWidgetContainer = styled.div`
interface BottomWidgetContainerProps {
hasPadding?: boolean;
width: number;
}

const BottomWidgetContainer = styled.div<BottomWidgetContainerProps>`
display: flex;
flex-direction: column;
padding-top: ${props => (props.hasPadding ? props.theme.bottomWidgetPaddingTop : 0)}px;
Expand All @@ -46,9 +53,22 @@ const BottomWidgetContainer = styled.div`
${media.portable`padding: 0;`}
`;

interface FilterAnimationControllerProps {
filter: TimeRangeFilter & {animationWindow?: string};
filterIdx: number;
setFilterAnimationTime: (idx: number, value: string, a: any[]) => void;
}

FilterAnimationControllerFactory.deps = [AnimationControllerFactory];
export function FilterAnimationControllerFactory(AnimationController: ReturnType<typeof AnimationControllerFactory>) {
const FilterAnimationController = ({filter, filterIdx, setFilterAnimationTime, children}) => {
export function FilterAnimationControllerFactory(
AnimationController: ReturnType<typeof AnimationControllerFactory>
) {
const FilterAnimationController: React.FC<FilterAnimationControllerProps> = ({
filter,
filterIdx,
setFilterAnimationTime,
children
}) => {
const intervalBins = useMemo(() => getIntervalBins(filter), [filter]);

const steps = useMemo(() => (intervalBins ? intervalBins.map(x => x.x0) : null), [
Expand Down Expand Up @@ -90,12 +110,23 @@ export function FilterAnimationControllerFactory(AnimationController: ReturnType
return FilterAnimationController;
}

interface LayerAnimationControllerProps {
animationConfig: AnimationConfig & {timeSteps?: number[] | null};
setLayerAnimationTime: (x: number) => void;
}

LayerAnimationControllerFactory.deps = [AnimationControllerFactory];
export function LayerAnimationControllerFactory(AnimationController: ReturnType<typeof AnimationControllerFactory>) {
const LayerAnimationController = ({animationConfig, setLayerAnimationTime, children}) => (
<AnimationController
export function LayerAnimationControllerFactory(
AnimationController: ReturnType<typeof AnimationControllerFactory>
) {
const LayerAnimationController: React.FC<LayerAnimationControllerProps> = ({
animationConfig,
setLayerAnimationTime,
children
}) => (
<AnimationController<number>
key="layer-control"
value={animationConfig.currentTime}
value={Number(animationConfig.currentTime)}
domain={animationConfig.domain}
speed={animationConfig.speed}
isAnimating={animationConfig.isAnimating}
Expand All @@ -110,6 +141,10 @@ export function LayerAnimationControllerFactory(AnimationController: ReturnType<
return LayerAnimationController;
}

type BottomWidgetProps = {
containerW: number;
} & ReturnType<typeof bottomWidgetSelector>;

BottomWidgetFactory.deps = [
TimeWidgetFactory,
AnimationControlFactory,
Expand All @@ -124,7 +159,7 @@ export default function BottomWidgetFactory(
FilterAnimationController: ReturnType<typeof FilterAnimationControllerFactory>,
LayerAnimationController: ReturnType<typeof LayerAnimationControllerFactory>
) {
const BottomWidget = props => {
const BottomWidget = (props: BottomWidgetProps) => {
const {
datasets,
filters,
Expand Down Expand Up @@ -172,7 +207,7 @@ export default function BottomWidgetFactory(

// if filter is not animating, pass in enlarged filter here because
// animation controller needs to call reset on it
const filter = animatedFilter || filters[enlargedFilterIdx];
const filter = (animatedFilter as TimeRangeFilter) || filters[enlargedFilterIdx];

return (
<BottomWidgetContainer
Expand Down Expand Up @@ -234,7 +269,7 @@ export default function BottomWidgetFactory(

/* eslint-disable react/display-name */
// @ts-ignore
return forwardRef((props, ref) => <BottomWidget {...props} rootRef={ref} />);
return forwardRef((props: BottomWidgetProps, ref) => <BottomWidget {...props} rootRef={ref} />);
/* eslint-enable react/display-name */
}
/* eslint-enable complexity */
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ const StyledDomain = styled.div.attrs({

AnimationControlFactory.deps = [PlaybackControlsFactory, FloatingTimeDisplayFactory];

function AnimationControlFactory(PlaybackControls: ReturnType<typeof PlaybackControlsFactory>, FloatingTimeDisplay: ReturnType<typeof FloatingTimeDisplayFactory>) {
function AnimationControlFactory(
PlaybackControls: ReturnType<typeof PlaybackControlsFactory>,
FloatingTimeDisplay: ReturnType<typeof FloatingTimeDisplayFactory>
) {
const AnimationControl = ({
isAnimatable,
isAnimating,
Expand Down
50 changes: 30 additions & 20 deletions src/components/common/animation-control/animation-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,22 @@ import {requestAnimationFrame, cancelAnimationFrame} from 'global/window';
import Console from 'global/console';
import {BASE_SPEED, FPS, ANIMATION_WINDOW} from 'constants/default-settings';

type AnimationControllerProps = {
interface AnimationControllerProps<T extends number | number[]> {
isAnimating?: boolean;
speed?: number;
updateAnimation: Function;
updateAnimation: (x: T) => void;
animationWindow?: string;
steps?: number[] | null;
domain: number[];
value: number[];
domain: number[] | null;
value: T;
baseSpeed?: number;
}

function AnimationControllerFactory() {
class AnimationControllerType<T extends number | number[]> extends Component<
AnimationControllerProps<T>
> {}

function AnimationControllerFactory(): typeof AnimationControllerType {
/**
* 4 Animation Window Types
* 1. free
Expand All @@ -58,15 +62,16 @@ function AnimationControllerFactory() {
* Current time is a point. An array of sorted time steps are provided,
* animate a moving point jumps to the next step
*/
class AnimationController extends Component<AnimationControllerProps> {

class AnimationController<T extends number | number[]> extends Component<
AnimationControllerProps<T>
> {
static defaultProps = {
baseSpeed: BASE_SPEED,
speed: 1,
steps: null,
animationWindow: ANIMATION_WINDOW.free
};

state = {
isAnimating: false
};
Expand All @@ -86,7 +91,7 @@ function AnimationControllerFactory() {
}

_timer = null;
_startTime: number | undefined;
_startTime: number = 0;

_startOrPauseAnimation() {
const {isAnimating, speed = 1} = this.props;
Expand All @@ -102,7 +107,6 @@ function AnimationControllerFactory() {

const loop = () => {
const current = new Date().getTime();
// @ts-ignore
const delta = current - this._startTime;

if (delta >= delay) {
Expand All @@ -118,22 +122,25 @@ function AnimationControllerFactory() {

_resetAnimationByDomain = () => {
const {domain, value, animationWindow} = this.props;
if (!domain) {
return;
}
if (Array.isArray(value)) {
if (animationWindow === ANIMATION_WINDOW.incremental) {
this.props.updateAnimation([value[0], value[0] + 1]);
this.props.updateAnimation([value[0], value[0] + 1] as T);
} else {
this.props.updateAnimation([domain[0], domain[0] + value[1] - value[0]]);
this.props.updateAnimation([domain[0], domain[0] + value[1] - value[0]] as T);
}
} else {
this.props.updateAnimation(domain[0]);
this.props.updateAnimation(domain[0] as T);
}
};

_resetAnimtionByTimeStep = () => {
const {steps = null} = this.props
const {steps = null} = this.props;
if (!steps) return;
// go to the first steps
this.props.updateAnimation([steps[0], 0]);
this.props.updateAnimation([steps[0], 0] as T);
};

_resetAnimation = () => {
Expand Down Expand Up @@ -186,18 +193,21 @@ function AnimationControllerFactory() {
? this._nextFrameByTimeStep()
: this._nextFrameByDomain();

this.props.updateAnimation(nextValue);
this.props.updateAnimation(nextValue as T);
};

_nextFrameByDomain() {
const {domain, value, speed = 1, baseSpeed = 600, animationWindow} = this.props;
if (!domain) {
return;
}
const delta = ((domain[1] - domain[0]) / baseSpeed) * speed;

// loop when reaches the end
// current time is a range
if (Array.isArray(value)) {
let value0;
let value1;
let value0: number;
let value1: number;
const readEnd = value[1] + delta > domain[1];
if (animationWindow === ANIMATION_WINDOW.incremental) {
value0 = value[0];
Expand All @@ -210,13 +220,13 @@ function AnimationControllerFactory() {
}

// current time is a point
return value + delta > domain[1] ? domain[0] : value + delta;
return Number(value) + delta > domain[1] ? domain[0] : Number(value) + delta;
}

_nextFrameByTimeStep() {
const {steps = null, value} = this.props;
if (!steps) return;
const val = Array.isArray(value) ? value[0] : value;
const val = Array.isArray(value) ? value[0] : Number(value);
const index = bisectLeft(steps, val);
const nextIdx = index >= steps.length - 1 ? 0 : index + 1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import React, {Component} from 'react';
import React, {Component, ComponentType} from 'react';
import styled from 'styled-components';
import RangeSliderFactory from 'components/common/range-slider';
import onClickOutside from 'react-onclickoutside';
Expand Down Expand Up @@ -48,10 +48,12 @@ AnimationSpeedSliderFactory.deps = [RangeSliderFactory];
interface AnimationSpeedSliderProps {
onHide: () => void;
speed: number;
updateAnimationSpeed: (val: number) => void
updateAnimationSpeed: (val: number) => void;
}

export default function AnimationSpeedSliderFactory(RangeSlider: ReturnType<typeof RangeSliderFactory>) {
export default function AnimationSpeedSliderFactory(
RangeSlider: ReturnType<typeof RangeSliderFactory>
): ComponentType<AnimationSpeedSliderProps> {
class AnimationSpeedSlider extends Component<AnimationSpeedSliderProps> {
handleClickOutside = e => {
this.props.onHide();
Expand Down
21 changes: 13 additions & 8 deletions src/components/common/animation-control/floating-time-display.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ const TimeDivider = () => (
</StyledHorizontalBar>
);

interface TimeDisplayRowProps{
timeValues?: string[]
interface TimeDisplayRowProps {
timeValues?: string[];
}

const TimeDisplayRow = ({timeValues = []}: TimeDisplayRowProps) => (
Expand All @@ -119,14 +119,19 @@ const TimeDisplayRow = ({timeValues = []}: TimeDisplayRowProps) => (
);

interface FloatingTimeDisplayProps {
currentTime: number | number[],
defaultTimeFormat?: string,
timeFormat?: string,
timezone?: string
currentTime: number | number[];
defaultTimeFormat?: string;
timeFormat?: string;
timezone?: string;
}

export default function FloatingTimeDisplayFactory() {
const FloatingTimeDisplay = ({currentTime, defaultTimeFormat, timeFormat, timezone}: FloatingTimeDisplayProps) => {
const FloatingTimeDisplay = ({
currentTime,
defaultTimeFormat,
timeFormat,
timezone
}: FloatingTimeDisplayProps) => {
const {displayDate, displayTime} = useMemo(() => {
const groupTime = Array.isArray(currentTime) ? currentTime : [currentTime];
const hasUserFormat = typeof timeFormat === 'string';
Expand All @@ -140,7 +145,7 @@ export default function FloatingTimeDisplayFactory() {
displayTime: []
};
}
return groupTime.reduce<{displayDate: string[], displayTime: string[]}>(
return groupTime.reduce<{displayDate: string[]; displayTime: string[]}>(
(accu, curr) => {
const [dateFormat, datetimeFormat] = currentFormat.split(' ');
const dateString = dateFunc(dateFormat)(curr);
Expand Down