Skip to content
This repository has been archived by the owner on Sep 18, 2024. It is now read-only.

Commit

Permalink
rc-2
Browse files Browse the repository at this point in the history
  • Loading branch information
Traineratwot committed Jan 18, 2024
1 parent fdf2e23 commit 2818181
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 90 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "traineratwot/filament-openstreetmap",
"version": "1.0.0",
"version": "1.1.0",
"description": "This is my package filament-openstreetmap",
"keywords": [
"Traineratwot",
Expand All @@ -25,7 +25,7 @@
"filament/filament": "^3.2",
"filament/forms": "^3.2",
"illuminate/contracts": "^10.0",
"matanyadaev/laravel-eloquent-spatial": "^3.2",
"matanyadaev/laravel-eloquent-spatial": "*",
"spatie/laravel-package-tools": "^1.15.0"
},
"require-dev": {
Expand Down
18 changes: 16 additions & 2 deletions resources/css/index.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
@import '../../node_modules/ol/ol.css';
@import '../../node_modules/ol-geocoder/dist/ol-geocoder.min.css';

.gcd-txt-control {
color: #09090b !important;
.open-street-map {
position: relative;
.gcd-txt-control {
color: #09090b !important;
}

.center {
z-index: 9999 !important;
position: absolute;
border: solid 1px black;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
}
}
2 changes: 1 addition & 1 deletion resources/dist/filament-openstreetmap.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 18 additions & 18 deletions resources/dist/filament-openstreetmap.js

Large diffs are not rendered by default.

59 changes: 14 additions & 45 deletions resources/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,27 @@ import { Feature } from 'ol'
import { fromLonLat, ProjectionLike } from 'ol/proj'
import VectorSource from 'ol/source/Vector'
import VectorLayer from 'ol/layer/Vector'
import { Modify } from 'ol/interaction'
import { Point } from 'ol/geom'
import Geocoder from 'ol-geocoder'
import { Icon, Style } from 'ol/style'


class mPoint {
constructor(public point: Feature<Point>, public projection: ProjectionLike, public view: View) {
constructor(public view: View, public projection: ProjectionLike) {
}

public onChange(callback: (lon: number, lat: number) => void) {
this.point.on('change', () => {
this.view.on('change', () => {
const [lat, lon] = this.getCoordinates()
callback(lat, lon)
})
}

public getCoordinates() {
const geom = this.point.getGeometry()
if (geom === null) {
return [null, null]
}
geom.setProperties({
projection: this.projection,
})
return geom.getCoordinates()
return this.view.getCenter()
}

public setCoordinates(lat: number, lon: number) {
this.point.setGeometry(new Point(fromLonLat([lat, lon], this.projection)))
this.view.setCenter(fromLonLat([lat, lon], this.projection))
}
}
Expand Down Expand Up @@ -81,37 +72,6 @@ function GetPointMap(id: string, lat: number = 0, lon: number = 0) {
target:target,
view: view,
})

const modify = new Modify({
hitDetection: vectorLayer,
source: vectorSource,
});
modify.on(['modifystart', 'modifyend'], function (evt) {
target.style.cursor = evt.type === 'modifystart' ? 'grabbing' : 'pointer';
});
const overlaySource = modify.getOverlay().getSource();
overlaySource.on(['addfeature', 'removefeature'], function (evt: { type: string }) {
target.style.cursor = evt.type === 'addfeature' ? 'pointer' : '';
});

map.addInteraction(modify);
document.getElementById(`OSMap-${id}`)?.addEventListener('contextmenu', function(event) {
event.preventDefault()
const div = document.getElementsByClassName( `mouse-position-${id}`) as HTMLCollectionOf<HTMLDivElement>
if (div.length === 0) {
console.log('no mouse position')
return
}
const coordsText = div[0].innerText || null
if (coordsText === null) {
console.log('no mouse position')
return
}
const [lat, lon] = coordsText.split(',').map((s) => parseFloat(s))
point.setGeometry(new Point(fromLonLat([lat, lon], projection)))
return false
})

const geocoder = new Geocoder('nominatim', {
provider: 'osm',
lang: 'ru-RU', //en-US, fr-FR
Expand All @@ -134,10 +94,19 @@ function GetPointMap(id: string, lat: number = 0, lon: number = 0) {
}))
// application specific
view.setCenter(fromLonLat([coordinate[0], coordinate[1]], projection))
point.setGeometry(new Point(fromLonLat([coordinate[0], coordinate[1]], projection)))
})

function updateCenter() {
// Получаем новые координаты центра карты
const [lat, lon] = map.getView().getCenter()
// Обновляем координаты точки
point.getGeometry().setCoordinates([lat, lon])
}

map.on('movestart', updateCenter)
map.on('moveend', updateCenter)
target.classList.add('map-done')
return new mPoint(point, projection, view)
return new mPoint(view, projection)
}

window['traineratwot'] = {}
Expand Down
7 changes: 5 additions & 2 deletions resources/views/forms/components/map.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,20 @@
{{ $getLabel() }}
</x-slot>


<x-filament::input.wrapper
:disabled="$isDisabled"
:valid="! $errors->has($statePath)"
:attributes="
\Filament\Support\prepare_inherited_attributes($getExtraAttributeBag())
->class(['fi-fo-textarea overflow-hidden'])
"

>

<div id="OSMap-{{ $getId() }}" style="height: max(500px, 100%);width: max(100px, 100%)"></div>
<div class="open-street-map" id="OSMap-{{ $getId() }}" style="height: max(500px, 100%);width: max(100px, 100%)">
<div class="center"></div>
</div>

<textarea
{{
$getExtraInputAttributeBag()
Expand Down
44 changes: 24 additions & 20 deletions src/Forms/Components/MapInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
namespace Traineratwot\FilamentOpenStreetMap\Forms\Components;

use Closure;
use Exception;
use Filament\Forms\Components\Textarea;
use Illuminate\Support\Facades\Validator;
use MatanYadaev\EloquentSpatial\Objects\Point;
use Traineratwot\FilamentOpenStreetMap\Rules\GeoPoint;

class MapInput extends Textarea
{
Expand Down Expand Up @@ -50,6 +51,8 @@ protected function setUp(): void
break;
}
});

$this->rules([new GeoPoint()]);
}

/**
Expand Down Expand Up @@ -85,46 +88,47 @@ public function saveAsArray(): static
return $this;
}

/**
* @throws Exception
*/
protected function parseInput(mixed $state): array
{
if ($state instanceof Point) {
$validator = Validator::make([
'state' => $state
], [
'state' => ['required', new GeoPoint()],
]);
if ($validator->fails()) {
return [
'latitude' => $state->latitude,
'longitude' => $state->longitude,
'latitude' => 0,
'longitude' => 0,
];
}
if (is_string($state)) {
$_state = explode(',', $state);
if (count($_state) !== 2) {
throw new Exception("Invalid state: $state ");
}

if ($state instanceof Point) {
return [
'latitude' => (float) $_state[0],
'longitude' => (float) $_state[1],
'latitude' => $state->latitude,
'longitude' => $state->longitude,
];
}

if (is_array($state)) {

if (isset($state['type']) && $state['type'] === 'Point') {

return [
'latitude' => $state['coordinates'][1],
'longitude' => $state['coordinates'][0],
];
}
if (count($state) !== 2) {
throw new Exception('Invalid state: '.json_encode($state));
}

return [
'latitude' => (float) $state[0],
'longitude' => (float) $state[1],
];
}

if (is_string($state)) {
$_state = explode(',', $state);
return [
'latitude' => (float)$_state[0],
'longitude' => (float)$_state[1],
];
}
return [
'latitude' => $this->latitude,
'longitude' => $this->longitude,
Expand Down
67 changes: 67 additions & 0 deletions src/Rules/GeoPoint.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace Traineratwot\FilamentOpenStreetMap\Rules;

use Closure;
use Exception;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Translation\PotentiallyTranslatedString;
use MatanYadaev\EloquentSpatial\Objects\Point;

class GeoPoint implements ValidationRule
{
/**
* Run the validation rule.
*
* @param Closure(string): PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
try {
$point = null;
if ($value instanceof Point) {
$point = [
'latitude' => $value->latitude,
'longitude' => $value->longitude,
];
}
if (is_string($value)) {
$_value = explode(',', $value);
if (count($_value) !== 2) {
$fail("The {$attribute} must be a valid geo point.");
}

$point = [
'latitude' => (float)$_value[0],
'longitude' => (float)$_value[1],
];
}
if (is_array($value)) {
if (isset($value['type']) && $value['type'] === 'Point') {
$point = [
'latitude' => $value['coordinates'][1],
'longitude' => $value['coordinates'][0],
];
} else if (count($value) !== 2) {
$fail("The {$attribute} must be a valid geo point.");
} else {
$point = [
'latitude' => (float)$value[0],
'longitude' => (float)$value[1],
];
}
}
if (!is_numeric($point['latitude']) || !is_numeric($point['longitude'])) {
$fail("The {$attribute} must be a valid geo point.");
}
if ($point['latitude'] < -90 || $point['latitude'] > 90) {
$fail("The {$attribute} must be a valid geo point.");
}
if ($point['longitude'] < -180 || $point['longitude'] > 180) {
$fail("The {$attribute} must be a valid geo point.");
}
} catch (Exception $e) {
$fail("The {$attribute} must be a valid geo point.");
}
}
}

0 comments on commit 2818181

Please sign in to comment.