More componenet migration

This commit is contained in:
HarelM
2023-12-23 15:40:27 +02:00
parent 90b692158a
commit 08f7a427f6
3 changed files with 83 additions and 63 deletions
+1
View File
@@ -10,6 +10,7 @@ import IconMissing from './IconMissing'
type IconLayerProps = { type IconLayerProps = {
type: string type: string
style?: object style?: object
className?: string
}; };
export default class IconLayer extends React.Component<IconLayerProps> { export default class IconLayer extends React.Component<IconLayerProps> {
@@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import classnames from 'classnames' import classnames from 'classnames'
import lodash from 'lodash'; import lodash from 'lodash';
@@ -8,20 +7,13 @@ import LayerListItem from './LayerListItem'
import ModalAdd from './ModalAdd' import ModalAdd from './ModalAdd'
import {SortableContainer} from 'react-sortable-hoc'; import {SortableContainer} from 'react-sortable-hoc';
import { LayerSpecification } from '@maplibre/maplibre-gl-style-spec';
const layerListPropTypes = { function layerPrefix(name: string) {
layers: PropTypes.array.isRequired,
selectedLayerIndex: PropTypes.number.isRequired,
onLayersChange: PropTypes.func.isRequired,
onLayerSelect: PropTypes.func,
sources: PropTypes.object.isRequired,
}
function layerPrefix(name) {
return name.replace(' ', '-').replace('_', '-').split('-')[0] return name.replace(' ', '-').replace('_', '-').split('-')[0]
} }
function findClosestCommonPrefix(layers, idx) { function findClosestCommonPrefix(layers: LayerSpecification[], idx: number) {
const currentLayerPrefix = layerPrefix(layers[idx].id) const currentLayerPrefix = layerPrefix(layers[idx].id)
let closestIdx = idx let closestIdx = idx
for (let i = idx; i > 0; i--) { for (let i = idx; i > 0; i--) {
@@ -37,14 +29,34 @@ function findClosestCommonPrefix(layers, idx) {
let UID = 0; 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 // List of collapsible layer editors
class LayerListContainer extends React.Component { class LayerListContainer extends React.Component<LayerListContainerProps, LayerListContainerState> {
static propTypes = {...layerListPropTypes}
static defaultProps = { static defaultProps = {
onLayerSelect: () => {}, onLayerSelect: () => {},
} }
selectedItemRef: React.RefObject<any>;
scrollContainerRef: React.RefObject<HTMLElement>;
constructor(props) { constructor(props: LayerListContainerProps) {
super(props); super(props);
this.selectedItemRef = React.createRef(); this.selectedItemRef = React.createRef();
this.scrollContainerRef = React.createRef(); this.scrollContainerRef = React.createRef();
@@ -60,7 +72,7 @@ class LayerListContainer extends React.Component {
} }
} }
toggleModal(modalName) { toggleModal(modalName: string) {
this.setState({ this.setState({
keys: { keys: {
...this.state.keys, ...this.state.keys,
@@ -74,9 +86,9 @@ class LayerListContainer extends React.Component {
} }
toggleLayers = () => { toggleLayers = () => {
let idx=0 let idx = 0
let newGroups=[] let newGroups: {[key:string]: boolean} = {}
this.groupedLayers().forEach(layers => { this.groupedLayers().forEach(layers => {
const groupPrefix = layerPrefix(layers[0].id) const groupPrefix = layerPrefix(layers[0].id)
@@ -87,7 +99,7 @@ class LayerListContainer extends React.Component {
newGroups[lookupKey] = this.state.areAllGroupsExpanded newGroups[lookupKey] = this.state.areAllGroupsExpanded
} }
layers.forEach((layer) => { layers.forEach((_layer) => {
idx += 1 idx += 1
}) })
}); });
@@ -98,7 +110,7 @@ class LayerListContainer extends React.Component {
}) })
} }
groupedLayers() { groupedLayers(): (LayerSpecification & {key: string})[][] {
const groups = [] const groups = []
const layerIdCount = new Map(); const layerIdCount = new Map();
@@ -122,7 +134,7 @@ class LayerListContainer extends React.Component {
return groups return groups
} }
toggleLayerGroup(groupPrefix, idx) { toggleLayerGroup(groupPrefix: string, idx: number) {
const lookupKey = [groupPrefix, idx].join('-') const lookupKey = [groupPrefix, idx].join('-')
const newGroups = { ...this.state.collapsedGroups } const newGroups = { ...this.state.collapsedGroups }
if(lookupKey in this.state.collapsedGroups) { if(lookupKey in this.state.collapsedGroups) {
@@ -135,12 +147,12 @@ class LayerListContainer extends React.Component {
}) })
} }
isCollapsed(groupPrefix, idx) { isCollapsed(groupPrefix: string, idx: number) {
const collapsed = this.state.collapsedGroups[[groupPrefix, idx].join('-')] const collapsed = this.state.collapsedGroups[[groupPrefix, idx].join('-')]
return collapsed === undefined ? true : collapsed return collapsed === undefined ? true : collapsed
} }
shouldComponentUpdate (nextProps, nextState) { shouldComponentUpdate (nextProps: LayerListContainerProps, nextState: LayerListContainerState) {
// Always update on state change // Always update on state change
if (this.state !== nextState) { if (this.state !== nextState) {
return true; return true;
@@ -148,8 +160,8 @@ class LayerListContainer extends React.Component {
// This component tree only requires id and visibility from the layers // This component tree only requires id and visibility from the layers
// objects // objects
function getRequiredProps (layer) { function getRequiredProps(layer: LayerSpecification) {
const out = { const out: {id: string, layout?: { visibility: any}} = {
id: layer.id, id: layer.id,
}; };
@@ -165,10 +177,10 @@ class LayerListContainer extends React.Component {
this.props.layers.map(getRequiredProps), this.props.layers.map(getRequiredProps),
); );
function withoutLayers (props) { function withoutLayers(props: LayerListContainerProps) {
const out = { const out = {
...props ...props
}; } as LayerListContainerProps & { layers?: any };
delete out['layers']; delete out['layers'];
return out; return out;
} }
@@ -184,7 +196,7 @@ class LayerListContainer extends React.Component {
return propsChanged; return propsChanged;
} }
componentDidUpdate (prevProps) { componentDidUpdate (prevProps: LayerListContainerProps) {
if (prevProps.selectedLayerIndex !== this.props.selectedLayerIndex) { if (prevProps.selectedLayerIndex !== this.props.selectedLayerIndex) {
const selectedItemNode = this.selectedItemRef.current; const selectedItemNode = this.selectedItemRef.current;
if (selectedItemNode && selectedItemNode.node) { if (selectedItemNode && selectedItemNode.node) {
@@ -207,7 +219,7 @@ class LayerListContainer extends React.Component {
render() { render() {
const listItems = [] const listItems: JSX.Element[] = []
let idx = 0 let idx = 0
const layersByGroup = this.groupedLayers(); const layersByGroup = this.groupedLayers();
layersByGroup.forEach(layers => { layersByGroup.forEach(layers => {
@@ -235,7 +247,7 @@ class LayerListContainer extends React.Component {
); );
}); });
const additionalProps = {}; const additionalProps: {ref?: React.RefObject<any>} = {};
if (idx === this.props.selectedLayerIndex) { if (idx === this.props.selectedLayerIndex) {
additionalProps.ref = this.selectedItemRef; additionalProps.ref = this.selectedItemRef;
} }
@@ -255,7 +267,7 @@ class LayerListContainer extends React.Component {
visibility={(layer.layout || {}).visibility} visibility={(layer.layout || {}).visibility}
isSelected={idx === this.props.selectedLayerIndex} isSelected={idx === this.props.selectedLayerIndex}
onLayerSelect={this.props.onLayerSelect} onLayerSelect={this.props.onLayerSelect}
onLayerDestroy={this.props.onLayerDestroy.bind(this)} onLayerDestroy={this.props.onLayerDestroy?.bind(this)}
onLayerCopy={this.props.onLayerCopy.bind(this)} onLayerCopy={this.props.onLayerCopy.bind(this)}
onLayerVisibilityToggle={this.props.onLayerVisibilityToggle.bind(this)} onLayerVisibilityToggle={this.props.onLayerVisibilityToggle.bind(this)}
{...additionalProps} {...additionalProps}
@@ -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 { type LayerListProps = LayerListContainerProps & {
static propTypes = {...layerListPropTypes} onMoveLayer(...args: unknown[]): unknown
};
export default class LayerList extends React.Component<LayerListProps> {
render() { render() {
return <LayerListContainerSortable return <LayerListContainerSortable
{...this.props} {...this.props}
@@ -8,7 +8,12 @@ import IconLayer from './IconLayer'
import {SortableElement, SortableHandle} from 'react-sortable-hoc' 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"> return <div className="maputnik-layer-list-item-handle">
<IconLayer <IconLayer
className="layer-handle__icon" className="layer-handle__icon"
@@ -20,15 +25,15 @@ const DraggableLabel = SortableHandle((props) => {
</div> </div>
}); });
class IconAction extends React.Component { type IconActionProps = {
static propTypes = { action: string
action: PropTypes.string.isRequired, onClick(...args: unknown[]): unknown
onClick: PropTypes.func.isRequired, wdKey?: string
wdKey: PropTypes.string, classBlockName?: string
classBlockName: PropTypes.string, classBlockModifier?: string
classBlockModifier: PropTypes.string, };
}
class IconAction extends React.Component<IconActionProps> {
renderIcon() { renderIcon() {
switch(this.props.action) { switch(this.props.action) {
case 'duplicate': return <MdContentCopy /> case 'duplicate': return <MdContentCopy />
@@ -51,7 +56,7 @@ class IconAction extends React.Component {
} }
return <button return <button
tabIndex="-1" tabIndex={-1}
title={this.props.action} title={this.props.action}
className={`maputnik-layer-list-icon-action ${classAdditions}`} className={`maputnik-layer-list-icon-action ${classAdditions}`}
data-wd-key={this.props.wdKey} data-wd-key={this.props.wdKey}
@@ -63,21 +68,21 @@ class IconAction extends React.Component {
} }
} }
class LayerListItem extends React.Component { type LayerListItemProps = {
static propTypes = { id?: string
layerIndex: PropTypes.number.isRequired, layerIndex: number
layerId: PropTypes.string.isRequired, layerId: string
layerType: PropTypes.string.isRequired, layerType: string
isSelected: PropTypes.bool, isSelected?: boolean
visibility: PropTypes.string, visibility?: string
className: PropTypes.string, className?: string
onLayerSelect(...args: unknown[]): unknown
onLayerSelect: PropTypes.func.isRequired, onLayerCopy?(...args: unknown[]): unknown
onLayerCopy: PropTypes.func, onLayerDestroy?(...args: unknown[]): unknown
onLayerDestroy: PropTypes.func, onLayerVisibilityToggle?(...args: unknown[]): unknown
onLayerVisibilityToggle: PropTypes.func, };
}
class LayerListItem extends React.Component<LayerListItemProps> {
static defaultProps = { static defaultProps = {
isSelected: false, isSelected: false,
visibility: 'visible', visibility: 'visible',
@@ -102,12 +107,12 @@ class LayerListItem extends React.Component {
return <li return <li
id={this.props.id} id={this.props.id}
key={this.props.layerId} 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} data-wd-key={"layer-list-item:"+this.props.layerId}
className={classnames({ className={classnames({
"maputnik-layer-list-item": true, "maputnik-layer-list-item": true,
"maputnik-layer-list-item-selected": this.props.isSelected, "maputnik-layer-list-item-selected": this.props.isSelected,
[this.props.className]: true, [this.props.className!]: true,
})}> })}>
<DraggableLabel {...this.props} /> <DraggableLabel {...this.props} />
<span style={{flexGrow: 1}} /> <span style={{flexGrow: 1}} />
@@ -115,25 +120,25 @@ class LayerListItem extends React.Component {
wdKey={"layer-list-item:"+this.props.layerId+":delete"} wdKey={"layer-list-item:"+this.props.layerId+":delete"}
action={'delete'} action={'delete'}
classBlockName="delete" classBlockName="delete"
onClick={e => this.props.onLayerDestroy(this.props.layerIndex)} onClick={_e => this.props.onLayerDestroy!(this.props.layerIndex)}
/> />
<IconAction <IconAction
wdKey={"layer-list-item:"+this.props.layerId+":copy"} wdKey={"layer-list-item:"+this.props.layerId+":copy"}
action={'duplicate'} action={'duplicate'}
classBlockName="duplicate" classBlockName="duplicate"
onClick={e => this.props.onLayerCopy(this.props.layerIndex)} onClick={_e => this.props.onLayerCopy!(this.props.layerIndex)}
/> />
<IconAction <IconAction
wdKey={"layer-list-item:"+this.props.layerId+":toggle-visibility"} wdKey={"layer-list-item:"+this.props.layerId+":toggle-visibility"}
action={visibilityAction} action={visibilityAction}
classBlockName="visibility" classBlockName="visibility"
classBlockModifier={visibilityAction} classBlockModifier={visibilityAction}
onClick={e => this.props.onLayerVisibilityToggle(this.props.layerIndex)} onClick={_e => this.props.onLayerVisibilityToggle!(this.props.layerIndex)}
/> />
</li> </li>
} }
} }
const LayerListItemSortable = SortableElement((props) => <LayerListItem {...props} />); const LayerListItemSortable = SortableElement((props: LayerListItemProps) => <LayerListItem {...props} />);
export default LayerListItemSortable; export default LayerListItemSortable;