Add duplicate layer id check (#1262)

## Summary

<img width="437" alt="Screenshot 2025-07-05 at 00 29 02"
src="https://github.com/user-attachments/assets/ebf8b024-a340-4eac-b470-29fd8f080c0a"
/>

- show an error if a layer with an existing id is added
- keep Add Layer modal open until the id is unique

## Testing
- `npm run lint`
- `npm run build`


------
https://chatgpt.com/codex/tasks/task_e_6868498a46188331b16e7b6e120930a7
This commit is contained in:
Bart Louwers
2025-07-05 11:32:32 +02:00
committed by GitHub
parent 4b977fd33e
commit 533f647c71
9 changed files with 51 additions and 4 deletions

View File

@@ -19,6 +19,7 @@
### 🐞 Bug fixes
- Fix incorrect handing of network error response (#944)
- Show an error when adding a layer with a duplicate ID
- _...Add new stuff here..._
## 2.1.1

View File

@@ -272,6 +272,22 @@ describe("modals", () => {
});
describe("add layer", () => {
beforeEach(() => {
when.setStyle("layer");
when.modal.open();
});
it("shows duplicate id error", () => {
when.setValue("add-layer.layer-id.input", "background");
when.click("add-layer");
then(get.elementByTestId("modal:add-layer")).shouldExist();
then(get.element(".maputnik-modal-error")).shouldContainText(
"Layer ID already exists"
);
});
});
describe("sources", () => {
it("toggle");
});

View File

@@ -23,10 +23,16 @@ type ModalAddState = {
id: string
source?: string
'source-layer'?: string
error?: string | null
};
class ModalAddInternal extends React.Component<ModalAddInternalProps, ModalAddState> {
addLayer = () => {
if (this.props.layers.some(l => l.id === this.state.id)) {
this.setState({ error: this.props.t('Layer ID already exists') })
return
}
const changedLayers = this.props.layers.slice(0)
const layer: ModalAddState = {
id: this.state.id,
@@ -41,9 +47,10 @@ class ModalAddInternal extends React.Component<ModalAddInternalProps, ModalAddSt
}
changedLayers.push(layer as LayerSpecification)
this.props.onLayersChange(changedLayers)
this.props.onOpenToggle(false)
this.setState({ error: null }, () => {
this.props.onLayersChange(changedLayers)
this.props.onOpenToggle(false)
})
}
constructor(props: ModalAddInternalProps) {
@@ -51,6 +58,7 @@ class ModalAddInternal extends React.Component<ModalAddInternalProps, ModalAddSt
const state: ModalAddState = {
type: 'fill',
id: '',
error: null,
}
if(props.sources.length > 0) {
@@ -129,6 +137,21 @@ class ModalAddInternal extends React.Component<ModalAddInternalProps, ModalAddSt
const t = this.props.t;
const sources = this.getSources(this.state.type);
const layers = this.getLayersForSource(this.state.source!);
let errorElement;
if (this.state.error) {
errorElement = (
<div className="maputnik-modal-error">
{this.state.error}
<a
href="#"
onClick={() => this.setState({ error: null })}
className="maputnik-modal-error-close"
>
×
</a>
</div>
);
}
return <Modal
isOpen={this.props.isOpen}
@@ -137,12 +160,13 @@ class ModalAddInternal extends React.Component<ModalAddInternalProps, ModalAddSt
data-wd-key="modal:add-layer"
className="maputnik-add-modal"
>
{errorElement}
<div className="maputnik-add-layer">
<FieldId
value={this.state.id}
wdKey="add-layer.layer-id"
onChange={(v: string) => {
this.setState({ id: v })
this.setState({ id: v, error: null })
}}
/>
<FieldType

View File

@@ -72,6 +72,7 @@
"Collapse": "Einklappen",
"Expand": "Ausklappen",
"Add Layer": "Ebene hinzufügen",
"Layer ID already exists": "Layer-ID existiert bereits",
"Search": "Suche",
"Zoom:": "Zoom:",
"Close popup": "Popup schließen",

View File

@@ -72,6 +72,7 @@
"Collapse": "Réduire",
"Expand": "Développer",
"Add Layer": "Ajouter un calque",
"Layer ID already exists": "L'identifiant du calque existe déjà",
"Search": "Recherche",
"Zoom:": "Zoom :",
"Close popup": "Fermer la fenêtre",

View File

@@ -72,6 +72,7 @@
"Collapse": "הקטנה",
"Expand": "הגדלה",
"Add Layer": "הוספת שכבה",
"Layer ID already exists": "מזהה השכבה כבר קיים",
"Search": "חיפוש",
"Zoom:": "זום:",
"Close popup": "סגירת החלון",

View File

@@ -72,6 +72,7 @@
"Collapse": "Coprimi",
"Expand": "Espandi",
"Add Layer": "Aggiungi Livello",
"Layer ID already exists": "L'ID del layer esiste già",
"Search": "Cerca",
"Zoom:": "Zoom:",
"Close popup": "Chiudi popup",

View File

@@ -72,6 +72,7 @@
"Collapse": "畳む",
"Expand": "展開",
"Add Layer": "レイヤー追加",
"Layer ID already exists": "レイヤーIDは既に存在します",
"Search": "検索",
"Zoom:": "ズーム:",
"Close popup": "ポップアップを閉じる",

View File

@@ -72,6 +72,7 @@
"Collapse": "折叠",
"Expand": "展开",
"Add Layer": "添加图层",
"Layer ID already exists": "图层ID已存在",
"Search": "搜索",
"Zoom:": "缩放:",
"Close popup": "关闭弹出窗口",