mirror of
https://github.com/maputnik/editor.git
synced 2026-02-06 04:30:01 +00:00
A few more components migrated
This commit is contained in:
@@ -2,16 +2,16 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import ScrollContainer from './ScrollContainer'
|
||||
|
||||
class AppLayout extends React.Component {
|
||||
static propTypes = {
|
||||
toolbar: PropTypes.element.isRequired,
|
||||
layerList: PropTypes.element.isRequired,
|
||||
layerEditor: PropTypes.element,
|
||||
map: PropTypes.element.isRequired,
|
||||
bottom: PropTypes.element,
|
||||
modals: PropTypes.node,
|
||||
}
|
||||
type AppLayoutProps = {
|
||||
toolbar: React.ReactElement
|
||||
layerList: React.ReactElement
|
||||
layerEditor?: React.ReactElement
|
||||
map: React.ReactElement
|
||||
bottom?: React.ReactElement
|
||||
modals?: React.ReactNode
|
||||
};
|
||||
|
||||
class AppLayout extends React.Component<AppLayoutProps> {
|
||||
static childContextTypes = {
|
||||
reactIconBase: PropTypes.object
|
||||
}
|
||||
@@ -1,29 +1,28 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {formatLayerId} from '../util/format';
|
||||
import { StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
|
||||
|
||||
export default class AppMessagePanel extends React.Component {
|
||||
static propTypes = {
|
||||
errors: PropTypes.array,
|
||||
infos: PropTypes.array,
|
||||
mapStyle: PropTypes.object,
|
||||
onLayerSelect: PropTypes.func,
|
||||
currentLayer: PropTypes.object,
|
||||
selectedLayerIndex: PropTypes.number,
|
||||
}
|
||||
type AppMessagePanelProps = {
|
||||
errors?: unknown[]
|
||||
infos?: unknown[]
|
||||
mapStyle?: StyleSpecification
|
||||
onLayerSelect?(...args: unknown[]): unknown
|
||||
currentLayer?: object
|
||||
selectedLayerIndex?: number
|
||||
};
|
||||
|
||||
export default class AppMessagePanel extends React.Component<AppMessagePanelProps> {
|
||||
static defaultProps = {
|
||||
onLayerSelect: () => {},
|
||||
}
|
||||
|
||||
render() {
|
||||
const {selectedLayerIndex} = this.props;
|
||||
const errors = this.props.errors.map((error, idx) => {
|
||||
const errors = this.props.errors?.map((error: any, idx) => {
|
||||
let content;
|
||||
if (error.parsed && error.parsed.type === "layer") {
|
||||
const {parsed} = error;
|
||||
const {mapStyle, currentLayer} = this.props;
|
||||
const layerId = mapStyle.layers[parsed.data.index].id;
|
||||
const layerId = this.props.mapStyle?.layers[parsed.data.index].id;
|
||||
content = (
|
||||
<>
|
||||
Layer <span>{formatLayerId(layerId)}</span>: {parsed.data.message}
|
||||
@@ -32,7 +31,7 @@ export default class AppMessagePanel extends React.Component {
|
||||
—
|
||||
<button
|
||||
className="maputnik-message-panel__switch-button"
|
||||
onClick={() => this.props.onLayerSelect(parsed.data.index)}
|
||||
onClick={() => this.props.onLayerSelect!(parsed.data.index)}
|
||||
>
|
||||
switch to layer
|
||||
</button>
|
||||
@@ -49,7 +48,7 @@ export default class AppMessagePanel extends React.Component {
|
||||
</p>
|
||||
})
|
||||
|
||||
const infos = this.props.infos.map((m, i) => {
|
||||
const infos = this.props.infos?.map((m, i) => {
|
||||
return <p key={"info-"+i}>{m}</p>
|
||||
})
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import classnames from 'classnames'
|
||||
import {detect} from 'detect-browser';
|
||||
|
||||
@@ -9,27 +8,28 @@ import pkgJson from '../../package.json'
|
||||
|
||||
// This is required because of <https://stackoverflow.com/a/49846426>, there isn't another way to detect support that I'm aware of.
|
||||
const browser = detect();
|
||||
const colorAccessibilityFiltersEnabled = ['chrome', 'firefox'].indexOf(browser.name) > -1;
|
||||
const colorAccessibilityFiltersEnabled = ['chrome', 'firefox'].indexOf(browser!.name) > -1;
|
||||
|
||||
|
||||
class IconText extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
}
|
||||
type IconTextProps = {
|
||||
children?: React.ReactNode
|
||||
};
|
||||
|
||||
|
||||
class IconText extends React.Component<IconTextProps> {
|
||||
render() {
|
||||
return <span className="maputnik-icon-text">{this.props.children}</span>
|
||||
}
|
||||
}
|
||||
|
||||
class ToolbarLink extends React.Component {
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
href: PropTypes.string,
|
||||
onToggleModal: PropTypes.func,
|
||||
}
|
||||
type ToolbarLinkProps = {
|
||||
className?: string
|
||||
children?: React.ReactNode
|
||||
href?: string
|
||||
onToggleModal?(...args: unknown[]): unknown
|
||||
};
|
||||
|
||||
class ToolbarLink extends React.Component<ToolbarLinkProps> {
|
||||
render() {
|
||||
return <a
|
||||
className={classnames('maputnik-toolbar-link', this.props.className)}
|
||||
@@ -42,14 +42,14 @@ class ToolbarLink extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
class ToolbarLinkHighlighted extends React.Component {
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
href: PropTypes.string,
|
||||
onToggleModal: PropTypes.func
|
||||
}
|
||||
type ToolbarLinkHighlightedProps = {
|
||||
className?: string
|
||||
children?: React.ReactNode
|
||||
href?: string
|
||||
onToggleModal?(...args: unknown[]): unknown
|
||||
};
|
||||
|
||||
class ToolbarLinkHighlighted extends React.Component<ToolbarLinkHighlightedProps> {
|
||||
render() {
|
||||
return <a
|
||||
className={classnames('maputnik-toolbar-link', "maputnik-toolbar-link--highlighted", this.props.className)}
|
||||
@@ -64,12 +64,12 @@ class ToolbarLinkHighlighted extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
class ToolbarSelect extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
wdKey: PropTypes.string
|
||||
}
|
||||
type ToolbarSelectProps = {
|
||||
children?: React.ReactNode
|
||||
wdKey?: string
|
||||
};
|
||||
|
||||
class ToolbarSelect extends React.Component<ToolbarSelectProps> {
|
||||
render() {
|
||||
return <div
|
||||
className='maputnik-toolbar-select'
|
||||
@@ -80,13 +80,13 @@ class ToolbarSelect extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
class ToolbarAction extends React.Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.node,
|
||||
onClick: PropTypes.func,
|
||||
wdKey: PropTypes.string
|
||||
}
|
||||
type ToolbarActionProps = {
|
||||
children?: React.ReactNode
|
||||
onClick?(...args: unknown[]): unknown
|
||||
wdKey?: string
|
||||
};
|
||||
|
||||
class ToolbarAction extends React.Component<ToolbarActionProps> {
|
||||
render() {
|
||||
return <button
|
||||
className='maputnik-toolbar-action'
|
||||
@@ -98,22 +98,22 @@ class ToolbarAction extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default class AppToolbar extends React.Component {
|
||||
static propTypes = {
|
||||
mapStyle: PropTypes.object.isRequired,
|
||||
inspectModeEnabled: PropTypes.bool.isRequired,
|
||||
onStyleChanged: PropTypes.func.isRequired,
|
||||
// A new style has been uploaded
|
||||
onStyleOpen: PropTypes.func.isRequired,
|
||||
// A dict of source id's and the available source layers
|
||||
sources: PropTypes.object.isRequired,
|
||||
children: PropTypes.node,
|
||||
onToggleModal: PropTypes.func,
|
||||
onSetMapState: PropTypes.func,
|
||||
mapState: PropTypes.string,
|
||||
renderer: PropTypes.string,
|
||||
}
|
||||
type AppToolbarProps = {
|
||||
mapStyle: object
|
||||
inspectModeEnabled: boolean
|
||||
onStyleChanged(...args: unknown[]): unknown
|
||||
// A new style has been uploaded
|
||||
onStyleOpen(...args: unknown[]): unknown
|
||||
// A dict of source id's and the available source layers
|
||||
sources: object
|
||||
children?: React.ReactNode
|
||||
onToggleModal(...args: unknown[]): unknown
|
||||
onSetMapState(...args: unknown[]): unknown
|
||||
mapState?: string
|
||||
renderer?: string
|
||||
};
|
||||
|
||||
export default class AppToolbar extends React.Component<AppToolbarProps> {
|
||||
state = {
|
||||
isOpen: {
|
||||
settings: false,
|
||||
@@ -124,16 +124,16 @@ export default class AppToolbar extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleSelection(val) {
|
||||
handleSelection(val: string | undefined) {
|
||||
this.props.onSetMapState(val);
|
||||
}
|
||||
|
||||
onSkip = (target) => {
|
||||
onSkip = (target: string) => {
|
||||
if (target === "map") {
|
||||
document.querySelector(".maplibregl-canvas").focus();
|
||||
(document.querySelector(".maplibregl-canvas") as HTMLCanvasElement).focus();
|
||||
}
|
||||
else {
|
||||
const el = document.querySelector("#skip-target-"+target);
|
||||
const el = document.querySelector("#skip-target-"+target) as HTMLButtonElement;
|
||||
el.focus();
|
||||
}
|
||||
}
|
||||
@@ -190,21 +190,21 @@ export default class AppToolbar extends React.Component {
|
||||
<button
|
||||
data-wd-key="root:skip:layer-list"
|
||||
className="maputnik-toolbar-skip"
|
||||
onClick={e => this.onSkip("layer-list")}
|
||||
onClick={_e => this.onSkip("layer-list")}
|
||||
>
|
||||
Layers list
|
||||
</button>
|
||||
<button
|
||||
data-wd-key="root:skip:layer-editor"
|
||||
className="maputnik-toolbar-skip"
|
||||
onClick={e => this.onSkip("layer-editor")}
|
||||
onClick={_e => this.onSkip("layer-editor")}
|
||||
>
|
||||
Layer editor
|
||||
</button>
|
||||
<button
|
||||
data-wd-key="root:skip:map-view"
|
||||
className="maputnik-toolbar-skip"
|
||||
onClick={e => this.onSkip("map")}
|
||||
onClick={_e => this.onSkip("map")}
|
||||
>
|
||||
Map view
|
||||
</button>
|
||||
@@ -246,7 +246,7 @@ export default class AppToolbar extends React.Component {
|
||||
className="maputnik-select"
|
||||
data-wd-key="maputnik-select"
|
||||
onChange={(e) => this.handleSelection(e.target.value)}
|
||||
value={currentView.id}
|
||||
value={currentView?.id}
|
||||
>
|
||||
{views.filter(v => v.group === "general").map((item) => {
|
||||
return (
|
||||
@@ -1,18 +1,16 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import IconLayer from './IconLayer'
|
||||
import {latest} from '@maplibre/maplibre-gl-style-spec'
|
||||
|
||||
function groupFeaturesBySourceLayer(features) {
|
||||
const sources = {}
|
||||
function groupFeaturesBySourceLayer(features: any[]) {
|
||||
const sources = {} as any
|
||||
|
||||
let returnedFeatures = {};
|
||||
let returnedFeatures = {} as any;
|
||||
|
||||
features.forEach(feature => {
|
||||
if(returnedFeatures.hasOwnProperty(feature.layer.id)) {
|
||||
returnedFeatures[feature.layer.id]++
|
||||
|
||||
const featureObject = sources[feature.layer['source-layer']].find(f => f.layer.id === feature.layer.id)
|
||||
const featureObject = sources[feature.layer['source-layer']].find((f: any) => f.layer.id === feature.layer.id)
|
||||
|
||||
featureObject.counter = returnedFeatures[feature.layer.id]
|
||||
} else {
|
||||
@@ -26,14 +24,14 @@ function groupFeaturesBySourceLayer(features) {
|
||||
return sources
|
||||
}
|
||||
|
||||
class FeatureLayerPopup extends React.Component {
|
||||
static propTypes = {
|
||||
onLayerSelect: PropTypes.func.isRequired,
|
||||
features: PropTypes.array,
|
||||
zoom: PropTypes.number,
|
||||
}
|
||||
type FeatureLayerPopupProps = {
|
||||
onLayerSelect(...args: unknown[]): unknown
|
||||
features: any[]
|
||||
zoom?: number
|
||||
};
|
||||
|
||||
_getFeatureColor(feature, zoom) {
|
||||
class FeatureLayerPopup extends React.Component<FeatureLayerPopupProps> {
|
||||
_getFeatureColor(feature: any, _zoom?: number) {
|
||||
// Guard because openlayers won't have this
|
||||
if (!feature.layer.paint) {
|
||||
return;
|
||||
@@ -57,7 +55,6 @@ class FeatureLayerPopup extends React.Component {
|
||||
}
|
||||
|
||||
if(propName) {
|
||||
const propertySpec = latest["paint_"+feature.layer.type][propName];
|
||||
let color = feature.layer.paint[propName];
|
||||
return String(color);
|
||||
}
|
||||
@@ -78,7 +75,7 @@ class FeatureLayerPopup extends React.Component {
|
||||
const sources = groupFeaturesBySourceLayer(this.props.features)
|
||||
|
||||
const items = Object.keys(sources).map(vectorLayerId => {
|
||||
const layers = sources[vectorLayerId].map((feature, idx) => {
|
||||
const layers = sources[vectorLayerId].map((feature: any, idx: number) => {
|
||||
const featureColor = this._getFeatureColor(feature, this.props.zoom);
|
||||
|
||||
return <div
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react'
|
||||
import {throttle} from 'lodash';
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import MapMaplibreGlLayerPopup from './MapMaplibreGlLayerPopup';
|
||||
|
||||
@@ -9,10 +8,10 @@ import {apply} from 'ol-mapbox-style';
|
||||
import {Map, View, Overlay} from 'ol';
|
||||
|
||||
import {toLonLat} from 'ol/proj';
|
||||
import {toStringHDMS} from 'ol/coordinate';
|
||||
import { StyleSpecification } from '@maplibre/maplibre-gl-style-spec';
|
||||
|
||||
|
||||
function renderCoords (coords) {
|
||||
function renderCoords (coords: string[]) {
|
||||
if (!coords || coords.length < 2) {
|
||||
return null;
|
||||
}
|
||||
@@ -23,36 +22,49 @@ function renderCoords (coords) {
|
||||
}
|
||||
}
|
||||
|
||||
export default class MapOpenLayers extends React.Component {
|
||||
static propTypes = {
|
||||
onDataChange: PropTypes.func,
|
||||
mapStyle: PropTypes.object.isRequired,
|
||||
accessToken: PropTypes.string,
|
||||
style: PropTypes.object,
|
||||
onLayerSelect: PropTypes.func.isRequired,
|
||||
debugToolbox: PropTypes.bool.isRequired,
|
||||
replaceAccessTokens: PropTypes.func.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
}
|
||||
type MapOpenLayersProps = {
|
||||
onDataChange?(...args: unknown[]): unknown
|
||||
mapStyle: object
|
||||
accessToken?: string
|
||||
style?: object
|
||||
onLayerSelect(...args: unknown[]): unknown
|
||||
debugToolbox: boolean
|
||||
replaceAccessTokens(...args: unknown[]): unknown
|
||||
onChange(...args: unknown[]): unknown
|
||||
};
|
||||
|
||||
type MapOpenLayersState = {
|
||||
zoom: string
|
||||
rotation: string
|
||||
cursor: string[]
|
||||
center: string[]
|
||||
selectedFeatures?: any[]
|
||||
};
|
||||
|
||||
export default class MapOpenLayers extends React.Component<MapOpenLayersProps, MapOpenLayersState> {
|
||||
static defaultProps = {
|
||||
onMapLoaded: () => {},
|
||||
onDataChange: () => {},
|
||||
onLayerSelect: () => {},
|
||||
}
|
||||
updateStyle: any;
|
||||
map: any;
|
||||
container: HTMLDivElement | null = null;
|
||||
overlay: Overlay | undefined;
|
||||
popupContainer: HTMLElement | null = null;
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: MapOpenLayersProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
zoom: 0,
|
||||
rotation: 0,
|
||||
cursor: [],
|
||||
zoom: "0",
|
||||
rotation: "0",
|
||||
cursor: [] as string[],
|
||||
center: [],
|
||||
};
|
||||
this.updateStyle = throttle(this._updateStyle.bind(this), 200);
|
||||
}
|
||||
|
||||
_updateStyle(newMapStyle) {
|
||||
_updateStyle(newMapStyle: StyleSpecification) {
|
||||
if(!this.map) return;
|
||||
|
||||
// See <https://github.com/openlayers/ol-mapbox-style/issues/215#issuecomment-493198815>
|
||||
@@ -60,7 +72,7 @@ export default class MapOpenLayers extends React.Component {
|
||||
apply(this.map, newMapStyle);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
componentDidUpdate(prevProps: MapOpenLayersProps) {
|
||||
if (this.props.mapStyle !== prevProps.mapStyle) {
|
||||
this.updateStyle(
|
||||
this.props.replaceAccessTokens(this.props.mapStyle)
|
||||
@@ -70,7 +82,7 @@ export default class MapOpenLayers extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
this.overlay = new Overlay({
|
||||
element: this.popupContainer,
|
||||
element: this.popupContainer!,
|
||||
autoPan: true,
|
||||
autoPanAnimation: {
|
||||
duration: 250
|
||||
@@ -78,7 +90,7 @@ export default class MapOpenLayers extends React.Component {
|
||||
});
|
||||
|
||||
const map = new Map({
|
||||
target: this.container,
|
||||
target: this.container!,
|
||||
overlays: [this.overlay],
|
||||
view: new View({
|
||||
zoom: 1,
|
||||
@@ -98,7 +110,7 @@ export default class MapOpenLayers extends React.Component {
|
||||
|
||||
const onMoveEnd = () => {
|
||||
const zoom = map.getView().getZoom();
|
||||
const center = toLonLat(map.getView().getCenter());
|
||||
const center = toLonLat(map.getView().getCenter()!);
|
||||
|
||||
this.props.onChange({
|
||||
zoom,
|
||||
@@ -112,15 +124,15 @@ export default class MapOpenLayers extends React.Component {
|
||||
onMoveEnd();
|
||||
map.on('moveend', onMoveEnd);
|
||||
|
||||
map.on('postrender', (evt) => {
|
||||
const center = toLonLat(map.getView().getCenter());
|
||||
map.on('postrender', (_e) => {
|
||||
const center = toLonLat(map.getView().getCenter()!);
|
||||
this.setState({
|
||||
center: [
|
||||
center[0].toFixed(2),
|
||||
center[1].toFixed(2),
|
||||
],
|
||||
rotation: map.getView().getRotation().toFixed(2),
|
||||
zoom: map.getView().getZoom().toFixed(2)
|
||||
zoom: map.getView().getZoom()!.toFixed(2)
|
||||
});
|
||||
});
|
||||
|
||||
@@ -132,9 +144,9 @@ export default class MapOpenLayers extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
closeOverlay = (e) => {
|
||||
closeOverlay = (e: any) => {
|
||||
e.target.blur();
|
||||
this.overlay.setPosition(undefined);
|
||||
this.overlay!.setPosition(undefined);
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -1,3 +0,0 @@
|
||||
export function formatLayerId (id) {
|
||||
return id === "" ? "[empty_string]" : `'${id}'`;
|
||||
}
|
||||
3
src/util/format.ts
Normal file
3
src/util/format.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export function formatLayerId (id: string | undefined) {
|
||||
return id === "" ? "[empty_string]" : `'${id}'`;
|
||||
}
|
||||
Reference in New Issue
Block a user