Skip to content

Commit

Permalink
More componenet migration
Browse files Browse the repository at this point in the history
  • Loading branch information
HarelM committed Dec 23, 2023
1 parent 90b6921 commit 08f7a42
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 64 deletions.
1 change: 1 addition & 0 deletions src/components/IconLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import IconMissing from './IconMissing'
type IconLayerProps = {
type: string
style?: object
className?: string
};

export default class IconLayer extends React.Component<IconLayerProps> {
Expand Down
80 changes: 47 additions & 33 deletions src/components/LayerList.jsx → src/components/LayerList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames'
import lodash from 'lodash';

Expand All @@ -8,20 +7,13 @@ import LayerListItem from './LayerListItem'
import ModalAdd from './ModalAdd'

import {SortableContainer} from 'react-sortable-hoc';
import { LayerSpecification } from '@maplibre/maplibre-gl-style-spec';

const layerListPropTypes = {
layers: PropTypes.array.isRequired,
selectedLayerIndex: PropTypes.number.isRequired,
onLayersChange: PropTypes.func.isRequired,
onLayerSelect: PropTypes.func,
sources: PropTypes.object.isRequired,
}

function layerPrefix(name) {
function layerPrefix(name: string) {
return name.replace(' ', '-').replace('_', '-').split('-')[0]
}

function findClosestCommonPrefix(layers, idx) {
function findClosestCommonPrefix(layers: LayerSpecification[], idx: number) {
const currentLayerPrefix = layerPrefix(layers[idx].id)
let closestIdx = idx
for (let i = idx; i > 0; i--) {
Expand All @@ -37,14 +29,34 @@ function findClosestCommonPrefix(layers, idx) {

let UID = 0;

type LayerListContainerProps = {
layers: LayerSpecification[]
selectedLayerIndex: number
onLayersChange(...args: unknown[]): unknown
onLayerSelect(...args: unknown[]): unknown
onLayerDestroy?(...args: unknown[]): unknown
onLayerCopy(...args: unknown[]): unknown
onLayerVisibilityToggle(...args: unknown[]): unknown
sources: object
errors: any[]
};

type LayerListContainerState = {
collapsedGroups: {[ket: string]: boolean}
areAllGroupsExpanded: boolean
keys: {[key: string]: number}
isOpen: {[key: string]: boolean}
};

// List of collapsible layer editors
class LayerListContainer extends React.Component {
static propTypes = {...layerListPropTypes}
class LayerListContainer extends React.Component<LayerListContainerProps, LayerListContainerState> {
static defaultProps = {
onLayerSelect: () => {},
}
selectedItemRef: React.RefObject<any>;
scrollContainerRef: React.RefObject<HTMLElement>;

constructor(props) {
constructor(props: LayerListContainerProps) {
super(props);
this.selectedItemRef = React.createRef();
this.scrollContainerRef = React.createRef();
Expand All @@ -60,7 +72,7 @@ class LayerListContainer extends React.Component {
}
}

toggleModal(modalName) {
toggleModal(modalName: string) {
this.setState({
keys: {
...this.state.keys,
Expand All @@ -74,9 +86,9 @@ class LayerListContainer extends React.Component {
}

toggleLayers = () => {
let idx=0
let idx = 0

let newGroups=[]
let newGroups: {[key:string]: boolean} = {}

this.groupedLayers().forEach(layers => {
const groupPrefix = layerPrefix(layers[0].id)
Expand All @@ -87,7 +99,7 @@ class LayerListContainer extends React.Component {
newGroups[lookupKey] = this.state.areAllGroupsExpanded
}

layers.forEach((layer) => {
layers.forEach((_layer) => {
idx += 1
})
});
Expand All @@ -98,7 +110,7 @@ class LayerListContainer extends React.Component {
})
}

groupedLayers() {
groupedLayers(): (LayerSpecification & {key: string})[][] {
const groups = []
const layerIdCount = new Map();

Expand All @@ -122,7 +134,7 @@ class LayerListContainer extends React.Component {
return groups
}

toggleLayerGroup(groupPrefix, idx) {
toggleLayerGroup(groupPrefix: string, idx: number) {
const lookupKey = [groupPrefix, idx].join('-')
const newGroups = { ...this.state.collapsedGroups }
if(lookupKey in this.state.collapsedGroups) {
Expand All @@ -135,21 +147,21 @@ class LayerListContainer extends React.Component {
})
}

isCollapsed(groupPrefix, idx) {
isCollapsed(groupPrefix: string, idx: number) {
const collapsed = this.state.collapsedGroups[[groupPrefix, idx].join('-')]
return collapsed === undefined ? true : collapsed
}

shouldComponentUpdate (nextProps, nextState) {
shouldComponentUpdate (nextProps: LayerListContainerProps, nextState: LayerListContainerState) {
// Always update on state change
if (this.state !== nextState) {
return true;
}

// This component tree only requires id and visibility from the layers
// objects
function getRequiredProps (layer) {
const out = {
function getRequiredProps(layer: LayerSpecification) {
const out: {id: string, layout?: { visibility: any}} = {
id: layer.id,
};

Expand All @@ -165,10 +177,10 @@ class LayerListContainer extends React.Component {
this.props.layers.map(getRequiredProps),
);

function withoutLayers (props) {
function withoutLayers(props: LayerListContainerProps) {
const out = {
...props
};
} as LayerListContainerProps & { layers?: any };
delete out['layers'];
return out;
}
Expand All @@ -184,7 +196,7 @@ class LayerListContainer extends React.Component {
return propsChanged;
}

componentDidUpdate (prevProps) {
componentDidUpdate (prevProps: LayerListContainerProps) {
if (prevProps.selectedLayerIndex !== this.props.selectedLayerIndex) {
const selectedItemNode = this.selectedItemRef.current;
if (selectedItemNode && selectedItemNode.node) {
Expand All @@ -207,7 +219,7 @@ class LayerListContainer extends React.Component {

render() {

const listItems = []
const listItems: JSX.Element[] = []
let idx = 0
const layersByGroup = this.groupedLayers();
layersByGroup.forEach(layers => {
Expand Down Expand Up @@ -235,7 +247,7 @@ class LayerListContainer extends React.Component {
);
});

const additionalProps = {};
const additionalProps: {ref?: React.RefObject<any>} = {};
if (idx === this.props.selectedLayerIndex) {
additionalProps.ref = this.selectedItemRef;
}
Expand All @@ -255,7 +267,7 @@ class LayerListContainer extends React.Component {
visibility={(layer.layout || {}).visibility}
isSelected={idx === this.props.selectedLayerIndex}
onLayerSelect={this.props.onLayerSelect}
onLayerDestroy={this.props.onLayerDestroy.bind(this)}
onLayerDestroy={this.props.onLayerDestroy?.bind(this)}
onLayerCopy={this.props.onLayerCopy.bind(this)}
onLayerVisibilityToggle={this.props.onLayerVisibilityToggle.bind(this)}
{...additionalProps}
Expand Down Expand Up @@ -316,11 +328,13 @@ class LayerListContainer extends React.Component {
}
}

const LayerListContainerSortable = SortableContainer((props) => <LayerListContainer {...props} />)
const LayerListContainerSortable = SortableContainer((props: LayerListContainerProps) => <LayerListContainer {...props} />)

export default class LayerList extends React.Component {
static propTypes = {...layerListPropTypes}
type LayerListProps = LayerListContainerProps & {
onMoveLayer(...args: unknown[]): unknown
};

export default class LayerList extends React.Component<LayerListProps> {
render() {
return <LayerListContainerSortable
{...this.props}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ import IconLayer from './IconLayer'
import {SortableElement, SortableHandle} from 'react-sortable-hoc'


const DraggableLabel = SortableHandle((props) => {
type DraggableLabelProps = {
layerId: string
layerType: string
};

const DraggableLabel = SortableHandle((props: DraggableLabelProps) => {
return <div className="maputnik-layer-list-item-handle">
<IconLayer
className="layer-handle__icon"
Expand All @@ -20,15 +25,15 @@ const DraggableLabel = SortableHandle((props) => {
</div>
});

class IconAction extends React.Component {
static propTypes = {
action: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired,
wdKey: PropTypes.string,
classBlockName: PropTypes.string,
classBlockModifier: PropTypes.string,
}
type IconActionProps = {
action: string
onClick(...args: unknown[]): unknown
wdKey?: string
classBlockName?: string
classBlockModifier?: string
};

class IconAction extends React.Component<IconActionProps> {
renderIcon() {
switch(this.props.action) {
case 'duplicate': return <MdContentCopy />
Expand All @@ -51,7 +56,7 @@ class IconAction extends React.Component {
}

return <button
tabIndex="-1"
tabIndex={-1}
title={this.props.action}
className={`maputnik-layer-list-icon-action ${classAdditions}`}
data-wd-key={this.props.wdKey}
Expand All @@ -63,21 +68,21 @@ class IconAction extends React.Component {
}
}

class LayerListItem extends React.Component {
static propTypes = {
layerIndex: PropTypes.number.isRequired,
layerId: PropTypes.string.isRequired,
layerType: PropTypes.string.isRequired,
isSelected: PropTypes.bool,
visibility: PropTypes.string,
className: PropTypes.string,

onLayerSelect: PropTypes.func.isRequired,
onLayerCopy: PropTypes.func,
onLayerDestroy: PropTypes.func,
onLayerVisibilityToggle: PropTypes.func,
}

type LayerListItemProps = {
id?: string
layerIndex: number
layerId: string
layerType: string
isSelected?: boolean
visibility?: string
className?: string
onLayerSelect(...args: unknown[]): unknown
onLayerCopy?(...args: unknown[]): unknown
onLayerDestroy?(...args: unknown[]): unknown
onLayerVisibilityToggle?(...args: unknown[]): unknown
};

class LayerListItem extends React.Component<LayerListItemProps> {
static defaultProps = {
isSelected: false,
visibility: 'visible',
Expand All @@ -102,38 +107,38 @@ class LayerListItem extends React.Component {
return <li
id={this.props.id}
key={this.props.layerId}
onClick={e => this.props.onLayerSelect(this.props.layerIndex)}
onClick={_e => this.props.onLayerSelect(this.props.layerIndex)}
data-wd-key={"layer-list-item:"+this.props.layerId}
className={classnames({
"maputnik-layer-list-item": true,
"maputnik-layer-list-item-selected": this.props.isSelected,
[this.props.className]: true,
[this.props.className!]: true,
})}>
<DraggableLabel {...this.props} />
<span style={{flexGrow: 1}} />
<IconAction
wdKey={"layer-list-item:"+this.props.layerId+":delete"}
action={'delete'}
classBlockName="delete"
onClick={e => this.props.onLayerDestroy(this.props.layerIndex)}
onClick={_e => this.props.onLayerDestroy!(this.props.layerIndex)}
/>
<IconAction
wdKey={"layer-list-item:"+this.props.layerId+":copy"}
action={'duplicate'}
classBlockName="duplicate"
onClick={e => this.props.onLayerCopy(this.props.layerIndex)}
onClick={_e => this.props.onLayerCopy!(this.props.layerIndex)}
/>
<IconAction
wdKey={"layer-list-item:"+this.props.layerId+":toggle-visibility"}
action={visibilityAction}
classBlockName="visibility"
classBlockModifier={visibilityAction}
onClick={e => this.props.onLayerVisibilityToggle(this.props.layerIndex)}
onClick={_e => this.props.onLayerVisibilityToggle!(this.props.layerIndex)}
/>
</li>
}
}

const LayerListItemSortable = SortableElement((props) => <LayerListItem {...props} />);
const LayerListItemSortable = SortableElement((props: LayerListItemProps) => <LayerListItem {...props} />);

export default LayerListItemSortable;

0 comments on commit 08f7a42

Please sign in to comment.