feat(editor): restore 3-col HubView + hide AOI on non-geo dicts

Per user feedback:
- "hub view" — restore старый 3-col layout с central focused dict card +
  outgoing FK rail слева + refBy rail справа. Был simpler 2-col split,
  но user previously сказал "Связи и вкладка связи была удобнее" (старый
  hub более информативный + центральная карта показывает context).
  Revert к версии 5007e0f (pre-2-col-redesign).
- "aoi там где нет полей гео лишний" — InfoPanel AOI button теперь скрыт
  если schema dict не имеет geo properties. Heuristic: property name
  matches /geom|location|bbox|polygon|coordinates|geo/i OR format=geojson|wkt.
  Edge case: если active aoi уже set → button показывается чтобы clear.
This commit is contained in:
Zimin A.N.
2026-05-11 20:19:27 +03:00
parent 3e4d78906d
commit b0e19951b3
2 changed files with 198 additions and 176 deletions
@@ -577,6 +577,21 @@ function DictionaryDetail() {
const totalRecords = recordsResult.data?.length ?? 0
const scope = detailQuery.data?.scope
// Geo capability detection — для скрытия AOI button на non-geo dicts.
// Эвристика по schema properties: property name matches geom/location/
// bbox/polygon/coordinates, OR format=geojson. Не идеально (false negatives
// если backend хранит geometry separately в записи без schema mention),
// но в practice все geo-dicts имеют geometry property в schemaJson.
const hasGeoRecords = useMemo(() => {
const props = detailQuery.data?.schemaJson?.properties
if (!props) return false
for (const [key, p] of Object.entries(props)) {
if (/geom|location|bbox|polygon|coordinates|geo/i.test(key)) return true
if (p.format === 'geojson' || p.format === 'wkt') return true
}
return false
}, [detailQuery.data?.schemaJson])
return (
<div className="space-y-6">
{scope && (
@@ -601,7 +616,11 @@ function DictionaryDetail() {
actions={{
onTimeTravel: () => setTimeTravelOpen((v) => !v),
timeTravelActive: Boolean(timeTravelAt),
onAoi: () => setAoiOpen(true),
// AOI button показываем только если у этого dict есть geo data —
// хотя бы одна record имеет geometryWkt. На non-geo dicts кнопка
// лишняя. Per user feedback: "aoi там где нет полей гео лишний".
// Edge case: если active aoi уже set → показываем чтобы юзер мог clear.
onAoi: hasGeoRecords || aoi ? () => setAoiOpen(true) : undefined,
aoiActive: Boolean(aoi),
// Открываем ExportModal вместо immediate triggera — пользователь
// выбирает формат/scope/columns/encoding/delimiter.