Skip to content

Commit 7e1a270

Browse files
authored
Allow multipart geometries (#19)
1 parent 34d434a commit 7e1a270

8 files changed

Lines changed: 95 additions & 9 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ The **Geometry** field displays a leaflet map, with a set of configuration optio
5353
### Geometry Field
5454

5555
> [!IMPORTANT]
56-
> This field is designed to be used in conjunction with a database column of type `POINT`, `LINESTRING`, `POLYGON` or `GEOMETRY`. It currently does not support geometry types with multiple items like `MULTIPOINT`, `MULTILINESTRING`, `MULTIPOLYGON` or `GEOMETRYCOLLECTION`. This field expects the attribute value to be a valid [GeoJSON](https://geojson.org/) string. Make sure your model attribute stores and retrieves GeoJSON data as a string.
56+
> This field is designed to be used in conjunction with a database column of type `(MULTI)POINT`, `(MULTI)LINESTRING`, `(MULTI)POLYGON` or `GEOMETRY`. It currently does not support geometries with mixed types i.e. `GEOMETRYCOLLECTION`. This field expects the attribute value to be a valid [GeoJSON](https://geojson.org/) string. Make sure your model attribute stores and retrieves GeoJSON data as a string.
5757
5858
The form field can be used with no options, by simply adding this to your Filament
5959
form schema:
@@ -111,6 +111,7 @@ Geometry::make('location')
111111
DrawMode::Polygon,
112112
DrawMode::Rectangle,
113113
])
114+
->multipart(false)
114115
->drawControlPosition(ControlPosition::TopRight)
115116
```
116117

package-lock.json

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
},
2323
"dependencies": {
2424
"@geoman-io/leaflet-geoman-free": "^2.18",
25+
"@turf/combine": "^6.5.0",
26+
"@turf/flatten": "^6.5.0",
2527
"leaflet": "^1.9",
2628
"leaflet-gesture-handling": "^1.2.2",
2729
"leaflet.fullscreen": "^4.0.0"

resources/dist/filament-geometry.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

resources/js/index.js

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import * as LF from 'leaflet';
22
import 'leaflet.fullscreen';
33
import 'leaflet-gesture-handling';
44
import '@geoman-io/leaflet-geoman-free';
5+
import combine from '@turf/combine';
6+
import flatten from '@turf/flatten';
57

68
export default function filamentGeometry($wire, config) {
79
return {
@@ -31,6 +33,23 @@ export default function filamentGeometry($wire, config) {
3133
icon: this.createMarkerIcon(),
3234
})
3335
},
36+
onEachFeature: (feature, layer) => {
37+
layer.pm.getShape = function () {
38+
switch (feature.type) {
39+
case 'Point':
40+
case 'MultiPoint':
41+
return 'Marker';
42+
case 'LineString':
43+
case 'MultiLineString':
44+
return 'Line';
45+
case 'Polygon':
46+
case 'MultiPolygon':
47+
return 'Polygon';
48+
default:
49+
throw new Error(`Unsupported feature type: ${feature.type}`);
50+
}
51+
}
52+
},
3453
}).addTo(this.map)
3554

3655
if (this.drawItems.getLayers().length > 0) {
@@ -68,11 +87,21 @@ export default function filamentGeometry($wire, config) {
6887
return;
6988
}
7089

71-
if (confirm(config.lang.warning.limit)) {
72-
this.drawItems.clearLayers()
73-
} else {
74-
this.map.pm.disableDraw()
75-
this.map.pm.enableGlobalEditMode()
90+
const allowedShapes = [this.drawItems.getLayers()[0].pm.getShape()];
91+
if (allowedShapes[0] === 'Rectangle') {
92+
allowedShapes.push('Polygon')
93+
} else if (allowedShapes[0] === 'Polygon') {
94+
allowedShapes.push('Rectangle')
95+
}
96+
const allowedShapeEnabled = allowedShapes.some((shape) => this.map.pm.Draw[shape].enabled())
97+
98+
if (!this.config.multipart || !allowedShapeEnabled) {
99+
if (confirm(this.config.multipart ? config.lang.warning.limit_multipart : config.lang.warning.limit)) {
100+
this.drawItems.clearLayers()
101+
} else {
102+
this.map.pm.disableDraw()
103+
this.map.pm.enableGlobalEditMode()
104+
}
76105
}
77106
})
78107

@@ -97,14 +126,25 @@ export default function filamentGeometry($wire, config) {
97126

98127
updateGeoJson: function() {
99128
try {
100-
this.$wire.set(config.statePath, this.drawItems.getLayers()[0] ? JSON.stringify(this.drawItems.getLayers()[0].toGeoJSON().geometry) : null, true)
129+
let value = null;
130+
if (this.drawItems.getLayers().length) {
131+
if (this.config.multipart) {
132+
value = combine(this.drawItems.toGeoJSON()).features[0].geometry;
133+
} else {
134+
value = this.drawItems.getLayers()[0].toGeoJSON().geometry;
135+
}
136+
}
137+
138+
this.$wire.set(config.statePath, value ? JSON.stringify(value) : null, true)
101139
} catch (error) {
102140
console.error('Error updating GeoJSON:', error)
103141
}
104142
},
105143

106144
getGeoJsonFeature: function() {
107-
return JSON.parse(this.$wire.get(config.statePath))
145+
const parsed = JSON.parse(this.$wire.get(config.statePath))
146+
147+
return parsed ? flatten(parsed).features.map(feature => feature.geometry) : null
108148
},
109149

110150
destroy: function() {

resources/lang/en/geometry.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
return [
44
'warning' => [
55
'limit' => 'You can add a maximum of 1 object. Do you want to delete the current one and start over?',
6+
'limit_multipart' => 'You can use only one object type at a time. Do you want to delete the current objects and start over?',
67
],
78
];

resources/lang/nl/geometry.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
return [
44
'warning' => [
55
'limit' => 'U kunt maximaal 1 object toevoegen. Wilt u de huidige verwijderen en opnieuw beginnen?',
6+
'limit_multipart' => 'U kunt maximaal één object type tegelijk gebruiken. Wilt u de huidige objecten verwijderen en opnieuw beginnen?',
67
],
78
];

src/Forms/Geometry.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class Geometry extends Field
2424

2525
private string $locale = 'en';
2626

27+
private bool $multipart = false;
28+
2729
/**
2830
* @var array<string, mixed>
2931
*/
@@ -86,6 +88,16 @@ public function drawModes(array $drawModes = []): self
8688
return $this;
8789
}
8890

91+
/**
92+
* @return $this
93+
*/
94+
public function multipart(bool $multipart = true): self
95+
{
96+
$this->multipart = $multipart;
97+
98+
return $this;
99+
}
100+
89101
/**
90102
* Create json configuration string
91103
*/
@@ -97,6 +109,7 @@ public function getMapConfig(): string
97109
'bounds' => $this->bounds?->toArray(),
98110
'map' => $this->mapOptions,
99111
'geoman' => $this->geomanOptions,
112+
'multipart' => $this->multipart,
100113
'locale' => $this->locale,
101114
'markerIcon' => $this->markerIcon->options(),
102115
'tileLayer' => [

0 commit comments

Comments
 (0)