mirror of
https://github.com/maputnik/editor.git
synced 2026-08-30 08:57:27 +00:00
58edd262b0
This is a rough start on adding react-i18next. I'll be working on adding more translatable strings and translations in the coming days. I'm going to need to wrap class components in HOCs, so let me know if there's something I should be fixing before doing that. I'm thinking now to keep the exported class names exactly the same, and rename the existing classes by prefixing an `I` (for internal). For example: ``` export default class AppToolbar ... ``` becomes ``` class IAppToolbar ... const AppToolbar = withTranslation()(IAppToolbar); export default AppToolbar; ``` I'll be able to contribute Japanese strings (I've talked to a couple people on my team and they'll be happy to help as well), so that's the language I decided to go with in this PR. Closes #746 --------- Co-authored-by: Ko Nagase <nagase@georepublic.co.jp> Co-authored-by: Harel M <harel.mazor@gmail.com>
183 lines
4.8 KiB
TypeScript
183 lines
4.8 KiB
TypeScript
import React from 'react'
|
|
|
|
import InputButton from './InputButton'
|
|
import Modal from './Modal'
|
|
import FieldType from './FieldType'
|
|
import FieldId from './FieldId'
|
|
import FieldSource from './FieldSource'
|
|
import FieldSourceLayer from './FieldSourceLayer'
|
|
import type {LayerSpecification} from 'maplibre-gl'
|
|
import { WithTranslation, withTranslation } from 'react-i18next';
|
|
|
|
type ModalAddInternalProps = {
|
|
layers: LayerSpecification[]
|
|
onLayersChange(layers: LayerSpecification[]): unknown
|
|
isOpen: boolean
|
|
onOpenToggle(open: boolean): unknown
|
|
// A dict of source id's and the available source layers
|
|
sources: any
|
|
} & WithTranslation;
|
|
|
|
type ModalAddState = {
|
|
type: LayerSpecification["type"]
|
|
id: string
|
|
source?: string
|
|
'source-layer'?: string
|
|
};
|
|
|
|
class ModalAddInternal extends React.Component<ModalAddInternalProps, ModalAddState> {
|
|
addLayer = () => {
|
|
const changedLayers = this.props.layers.slice(0)
|
|
const layer: ModalAddState = {
|
|
id: this.state.id,
|
|
type: this.state.type,
|
|
}
|
|
|
|
if(this.state.type !== 'background') {
|
|
layer.source = this.state.source
|
|
if(this.state.type !== 'raster' && this.state['source-layer']) {
|
|
layer['source-layer'] = this.state['source-layer']
|
|
}
|
|
}
|
|
|
|
changedLayers.push(layer as LayerSpecification)
|
|
|
|
this.props.onLayersChange(changedLayers)
|
|
this.props.onOpenToggle(false)
|
|
}
|
|
|
|
constructor(props: ModalAddInternalProps) {
|
|
super(props)
|
|
const state: ModalAddState = {
|
|
type: 'fill',
|
|
id: '',
|
|
}
|
|
|
|
if(props.sources.length > 0) {
|
|
state.source = Object.keys(this.props.sources)[0];
|
|
state['source-layer'] = this.props.sources[state.source as keyof ModalAddInternalProps["sources"]][0]
|
|
}
|
|
this.state = state;
|
|
}
|
|
|
|
componentDidUpdate(_prevProps: ModalAddInternalProps, prevState: ModalAddState) {
|
|
// Check if source is valid for new type
|
|
const oldType = prevState.type;
|
|
const newType = this.state.type;
|
|
|
|
const availableSourcesOld = this.getSources(oldType);
|
|
const availableSourcesNew = this.getSources(newType);
|
|
|
|
if(
|
|
// Type has changed
|
|
oldType !== newType
|
|
&& prevState.source !== ""
|
|
// Was a valid source previously
|
|
&& availableSourcesOld.indexOf(prevState.source!) > -1
|
|
// And is not a valid source now
|
|
&& availableSourcesNew.indexOf(this.state.source!) < 0
|
|
) {
|
|
// Clear the source
|
|
this.setState({
|
|
source: ""
|
|
});
|
|
}
|
|
}
|
|
|
|
getLayersForSource(source: string) {
|
|
const sourceObj = this.props.sources[source] || {};
|
|
return sourceObj.layers || [];
|
|
}
|
|
|
|
getSources(type: string) {
|
|
const sources = [];
|
|
|
|
const types = {
|
|
vector: [
|
|
"fill",
|
|
"line",
|
|
"symbol",
|
|
"circle",
|
|
"fill-extrusion",
|
|
"heatmap"
|
|
],
|
|
raster: [
|
|
"raster"
|
|
],
|
|
geojson: [
|
|
"fill",
|
|
"line",
|
|
"symbol",
|
|
"circle",
|
|
"fill-extrusion",
|
|
"heatmap"
|
|
]
|
|
}
|
|
|
|
for(const [key, val] of Object.entries(this.props.sources) as any) {
|
|
const valType = val.type as keyof typeof types;
|
|
if(types[valType] && types[valType].indexOf(type) > -1) {
|
|
sources.push(key);
|
|
}
|
|
}
|
|
|
|
return sources;
|
|
}
|
|
|
|
|
|
render() {
|
|
const t = this.props.t;
|
|
const sources = this.getSources(this.state.type);
|
|
const layers = this.getLayersForSource(this.state.source!);
|
|
|
|
return <Modal
|
|
isOpen={this.props.isOpen}
|
|
onOpenToggle={this.props.onOpenToggle}
|
|
title={t('Add Layer')}
|
|
data-wd-key="modal:add-layer"
|
|
className="maputnik-add-modal"
|
|
>
|
|
<div className="maputnik-add-layer">
|
|
<FieldId
|
|
value={this.state.id}
|
|
wdKey="add-layer.layer-id"
|
|
onChange={(v: string) => {
|
|
this.setState({ id: v })
|
|
}}
|
|
/>
|
|
<FieldType
|
|
value={this.state.type}
|
|
wdKey="add-layer.layer-type"
|
|
onChange={(v: LayerSpecification["type"]) => this.setState({ type: v })}
|
|
/>
|
|
{this.state.type !== 'background' &&
|
|
<FieldSource
|
|
sourceIds={sources}
|
|
wdKey="add-layer.layer-source-block"
|
|
value={this.state.source}
|
|
onChange={(v: string) => this.setState({ source: v })}
|
|
/>
|
|
}
|
|
{['background', 'raster', 'hillshade', 'heatmap'].indexOf(this.state.type) < 0 &&
|
|
<FieldSourceLayer
|
|
isFixed={true}
|
|
sourceLayerIds={layers}
|
|
value={this.state['source-layer']}
|
|
onChange={(v: string) => this.setState({ 'source-layer': v })}
|
|
/>
|
|
}
|
|
<InputButton
|
|
className="maputnik-add-layer-button"
|
|
onClick={this.addLayer}
|
|
data-wd-key="add-layer"
|
|
>
|
|
{t("Add Layer")}
|
|
</InputButton>
|
|
</div>
|
|
</Modal>
|
|
}
|
|
}
|
|
|
|
const ModalAdd = withTranslation()(ModalAddInternal);
|
|
export default ModalAdd;
|