feat(geo): AOI picker — Leaflet draw → bbox/polygon фильтр записей

Admin кликает 'AOI фильтр' на странице словаря → открывается
dialog с картой OSM. Рисует rectangle (→ bbox CSV) или
polygon → onApply применяется к recordsQuery как ?bbox= или
?polygon=GeoJSON.

Server-side parsing уже есть (BoundingBox.parse, GeoJsonPolygon.parse
в ordinis-rest-api) — подключили UI поверх.

Активный AOI отображается inline над таблицей с кнопкой
'Сбросить'. Edit shape возможен через leaflet-draw edit/remove
controls.

Зависимости: leaflet 1.9.4 + react-leaflet 5 + leaflet-draw 1.0.4
+ types. Bundle +231KB gzip 62KB — приемлемо для AOI-only feature
(map работает без MapLibre WASM, OSM tiles — публичные).

Picker self-contained: монтируется/уничтожается с диалогом,
invalidateSize 100ms после open чтобы Leaflet корректно посчитал
container size после modal animation.
This commit is contained in:
Zimin A.N.
2026-05-06 20:01:14 +03:00
parent 4fa96bffed
commit 05af8e1520
6 changed files with 405 additions and 8 deletions
+20
View File
@@ -235,6 +235,16 @@ i18n
'error.failed': 'Не удалось загрузить данные',
'auth.login': 'Войти',
'auth.logout': 'Выйти',
'aoi.button': 'AOI фильтр',
'aoi.activeBbox': 'AOI: bbox {{value}}',
'aoi.activePolygon': 'AOI: полигон ({{points}} точек)',
'aoi.clear': 'Сбросить AOI',
'aoi.dialog.title': 'Выбор области интереса (AOI)',
'aoi.dialog.help': 'Нарисуйте прямоугольник или полигон. Применяется как фильтр к записям со spatial geometry.',
'aoi.dialog.apply': 'Применить',
'aoi.dialog.mapAriaLabel': 'Карта для выбора области интереса',
'aoi.error.noShape': 'Сначала нарисуйте область на карте',
'aoi.error.invalid': 'Геометрия некорректна — попробуйте перерисовать',
},
},
'en-US': {
@@ -460,6 +470,16 @@ i18n
'error.failed': 'Failed to load data',
'auth.login': 'Sign in',
'auth.logout': 'Sign out',
'aoi.button': 'AOI filter',
'aoi.activeBbox': 'AOI: bbox {{value}}',
'aoi.activePolygon': 'AOI: polygon ({{points}} points)',
'aoi.clear': 'Clear AOI',
'aoi.dialog.title': 'Select Area of Interest (AOI)',
'aoi.dialog.help': 'Draw a rectangle or polygon. Applied as filter to records with spatial geometry.',
'aoi.dialog.apply': 'Apply',
'aoi.dialog.mapAriaLabel': 'Map for selecting area of interest',
'aoi.error.noShape': 'Draw an area on the map first',
'aoi.error.invalid': 'Invalid geometry — please redraw',
},
},
},