refactor(important): change binđing geometry to bound_with(up side down tree)

This commit is contained in:
taDuc
2026-05-24 20:18:29 +07:00
parent a98e1ac5b0
commit 395eb3de47
31 changed files with 339 additions and 234 deletions
@@ -29,7 +29,7 @@ type GeometryRow = Required<Pick<GeometryChoice, "id" | "label" | "isOrphan" | "
type Props = {
geometries: GeometryChoice[];
selectedGeometryId?: string | null;
selectedGeometryBindingIds: string[];
selectedGeometryChildIds: string[];
onToggleBindGeometryForSelectedGeometry?: (geometryId: string, nextChecked: boolean) => void;
onFocusGeometry?: (geometryId: string) => void;
};
@@ -37,7 +37,7 @@ type Props = {
export default function GeometryBindingPanel({
geometries,
selectedGeometryId,
selectedGeometryBindingIds,
selectedGeometryChildIds,
onToggleBindGeometryForSelectedGeometry,
onFocusGeometry,
}: Props) {
@@ -85,7 +85,7 @@ export default function GeometryBindingPanel({
return cleaned;
}, [geometries]);
const bindingSet = useMemo(() => new Set(selectedGeometryBindingIds || []), [selectedGeometryBindingIds]);
const childSet = useMemo(() => new Set(selectedGeometryChildIds || []), [selectedGeometryChildIds]);
const selectedGeometry = useMemo(() => {
if (!effectiveSelectedGeometryId) return null;
return rows.find((g) => g.id === effectiveSelectedGeometryId) || null;
@@ -94,12 +94,12 @@ export default function GeometryBindingPanel({
return rows
.filter((g) => g.id !== effectiveSelectedGeometryId)
.sort((a, b) => {
const aBound = bindingSet.has(a.id);
const bBound = bindingSet.has(b.id);
const aBound = childSet.has(a.id);
const bBound = childSet.has(b.id);
if (aBound !== bBound) return aBound ? -1 : 1;
return a.id.localeCompare(b.id);
});
}, [bindingSet, effectiveSelectedGeometryId, rows]);
}, [childSet, effectiveSelectedGeometryId, rows]);
const summary = useMemo(() => {
let orphan = 0;
let missingTime = 0;
@@ -247,7 +247,7 @@ export default function GeometryBindingPanel({
{collapsed ? null : selectedGeometry ? (
(() => {
const isHidden = geometryVisibility[selectedGeometry.id] === false;
const isBound = bindingSet.has(selectedGeometry.id);
const isBound = childSet.has(selectedGeometry.id);
const title = buildGeometryTitle(selectedGeometry, isHidden, isBound);
return (
<div
@@ -306,7 +306,7 @@ export default function GeometryBindingPanel({
<div style={{ marginTop: "10px", display: "grid", gap: "6px", maxHeight: 250, overflowY: "auto", paddingRight: 4 }}>
{visibleRows
.map((g) => {
const isBound = bindingSet.has(g.id);
const isBound = childSet.has(g.id);
const isHidden = geometryVisibility[g.id] === false;
const title = buildGeometryTitle(g, isHidden, isBound);
return (
@@ -58,10 +58,8 @@ export default function SelectedGeometryPanel({
geometryMetaForm.type_key,
geometryMetaForm.time_start,
geometryMetaForm.time_end,
geometryMetaForm.binding,
].join("|");
}, [
geometryMetaForm.binding,
geometryMetaForm.time_end,
geometryMetaForm.time_start,
geometryMetaForm.type_key,
+17 -37
View File
@@ -13,6 +13,7 @@ import { PATH_RENDER_BY_TYPE } from "@/uhm/lib/map/styles/style";
import { getBackgroundRasterSourceSpecification } from "@/uhm/api/tiles";
import { newId } from "@/uhm/lib/utils/id";
import { normalizeGeoTypeKey } from "@/uhm/lib/map/geo/geoTypeMap";
import { normalizeBoundWithId, normalizeFeatureBoundWith } from "@/uhm/lib/editor/geometry/geometryBinding";
import type { EntityLabelCandidate } from "@/uhm/types/geo";
type Coordinate = [number, number];
@@ -149,9 +150,18 @@ export function filterDraftByBinding(
}
const childIds = new Set<string>();
const selectedChildren = new Set<string>();
const selectedParents = new Set<string>();
for (const feature of fc.features) {
for (const id of normalizeBindingIds(feature.properties.binding)) {
childIds.add(id);
const featureId = String(feature.properties.id);
const parentId = normalizeFeatureBoundWith(feature);
if (!parentId) continue;
childIds.add(featureId);
if (selectedIds.has(parentId)) {
selectedChildren.add(featureId);
}
if (selectedIds.has(featureId)) {
selectedParents.add(parentId);
}
}
@@ -159,21 +169,13 @@ export function filterDraftByBinding(
return { ...fc, features: fc.features.filter((f) => !childIds.has(String(f.properties.id))) };
}
const selectedChildren = new Set<string>();
for (const feature of fc.features) {
if (selectedIds.has(String(feature.properties.id))) {
for (const id of normalizeBindingIds(feature.properties.binding)) {
selectedChildren.add(id);
}
}
}
return {
...fc,
features: fc.features.filter((feature) => {
const featureId = String(feature.properties.id);
if (selectedIds.has(featureId)) return true;
if (selectedChildren.has(featureId)) return true;
if (selectedParents.has(featureId)) return true;
return !childIds.has(featureId);
}),
};
@@ -200,20 +202,6 @@ export function filterDraftByGeometryVisibility(
};
}
export function normalizeBindingIds(rawBinding: unknown): string[] {
if (!Array.isArray(rawBinding)) return [];
const deduped: string[] = [];
const seen = new Set<string>();
for (const rawId of rawBinding) {
if (typeof rawId !== "string" && typeof rawId !== "number") continue;
const id = String(rawId).trim();
if (!id || seen.has(id)) continue;
seen.add(id);
deduped.push(id);
}
return deduped;
}
export function splitDraftFeatures(fc: FeatureCollection) {
const polygons = {
type: "FeatureCollection",
@@ -683,21 +671,13 @@ function createFeatureLabelResolver(
}
for (const feature of fc.features) {
const parentLabel = directLabelsByFeatureId.get(String(feature.properties.id));
const featureId = String(feature.properties.id);
const bindingIds = normalizeBindingIds(feature.properties.binding);
const parentId = normalizeBoundWithId(feature.properties.bound_with);
if (!parentId) continue;
const parentLabel = directLabelsByFeatureId.get(parentId);
if (parentLabel) {
for (const childId of bindingIds) {
mergeInheritedFeatureLabel(inheritedLabelsByChildId, childId, parentLabel);
}
}
for (const parentId of bindingIds) {
const linkedParentLabel = directLabelsByFeatureId.get(parentId);
if (linkedParentLabel) {
mergeInheritedFeatureLabel(inheritedLabelsByChildId, featureId, linkedParentLabel);
}
mergeInheritedFeatureLabel(inheritedLabelsByChildId, featureId, parentLabel);
}
}
+6 -6
View File
@@ -135,7 +135,7 @@ export function useMapInteraction({
entity_ids: [],
entity_name: null,
entity_type_id: null,
binding: [],
bound_with: null,
},
geometry,
});
@@ -201,7 +201,7 @@ export function useMapInteraction({
entity_ids: [],
entity_name: null,
entity_type_id: null,
binding: [],
bound_with: null,
},
geometry,
});
@@ -223,7 +223,7 @@ export function useMapInteraction({
entity_ids: [],
entity_name: null,
entity_type_id: null,
binding: [],
bound_with: null,
},
geometry,
});
@@ -245,7 +245,7 @@ export function useMapInteraction({
entity_ids: [],
entity_name: null,
entity_type_id: null,
binding: [],
bound_with: null,
},
geometry,
});
@@ -267,7 +267,7 @@ export function useMapInteraction({
entity_ids: [],
entity_name: null,
entity_type_id: null,
binding: [],
bound_with: null,
},
geometry,
});
@@ -372,7 +372,7 @@ function buildDuplicatedFeatureShapeOnly(
entity_ids: [],
entity_name: null,
entity_names: [],
binding: [],
bound_with: null,
},
geometry,
};