basic Uer UI
Build and Release / release (push) Successful in 1m30s

This commit is contained in:
taDuc
2026-06-06 15:36:15 +07:00
parent 61949e7149
commit 820e0b5216
65 changed files with 3460 additions and 1322 deletions
+14 -49
View File
@@ -3,7 +3,7 @@
import { useCallback, useEffect, useMemo, useRef, useState, type SetStateAction } from "react";
import { useParams, useRouter } from "next/navigation";
import { useShallow } from "zustand/react/shallow";
import Map, { type MapHandle } from "@/uhm/components/Map";
import Map, { type MapFeaturePayload, type MapHandle } from "@/uhm/components/Map";
import Editor from "@/uhm/components/Editor";
import BackgroundLayersPanel from "@/uhm/components/editor/BackgroundLayersPanel";
import TimelineBar from "@/uhm/components/ui/TimelineBar";
@@ -423,6 +423,14 @@ function EditorPageContent() {
const isViewerPreviewMode = mode === "preview";
const isReplayPreviewMode = mode === "replay_preview";
const isAnyPreviewMode = isViewerPreviewMode || isReplayPreviewMode;
const isEditingGeometryOrReplay =
mode === "draw" ||
mode === "add-point" ||
mode === "add-line" ||
mode === "add-path" ||
mode === "add-circle" ||
mode === "replay" ||
(mode === "select" && selectedFeatureIds.length > 0);
const previewReturnModeRef = useRef<EditorMode>("select");
const replayPreviewReturnRef = useRef<{
mode: "replay" | "preview";
@@ -1172,12 +1180,12 @@ function EditorPageContent() {
}
}, [isReplayPreviewMode, isViewerPreviewMode, exitReplayPreview, openSelectedViewerReplayPreview, viewerPreviewSelectedReplay]);
const handleMapFeatureClick = useCallback((payload: any) => {
const handleMapFeatureClick = useCallback((payload: MapFeaturePayload | null) => {
previewLayoutRef.current?.handleFeatureClick(payload);
}, []);
const handleMapHoverPopupContent = useCallback((payload: any) => {
return previewLayoutRef.current?.getHoverPopupContent(payload) ?? null;
const handleMapHoverPopupContent = useCallback((feature: Feature) => {
return previewLayoutRef.current?.getHoverPopupContent(feature) ?? null;
}, []);
const handleMapPlayPreviewReplay = useCallback(() => {
@@ -2393,7 +2401,7 @@ function EditorPageContent() {
const handleCreateFeature = useCallback((feature: Feature) => {
editor.createFeature(feature);
setSelectedFeatureIds([feature.properties.id]);
}, [editor]);
}, [editor, setSelectedFeatureIds]);
// Base draft for label lookup only. It must not decide which geometry is rendered.
const labelContextBaseDraft = useMemo(() => {
@@ -2746,7 +2754,7 @@ function EditorPageContent() {
year={activeTimelineYear}
onYearChange={handleTimelineYearChange}
isLoading={false}
disabled={false}
disabled={isEditingGeometryOrReplay}
statusText={null}
filterEnabled={activeTimelineFilterEnabled}
onFilterEnabledChange={setTimelineFilterEnabled}
@@ -2923,49 +2931,6 @@ function isTypingTarget(target: EventTarget | null): boolean {
return tagName === "input" || tagName === "textarea" || tagName === "select" || target.isContentEditable;
}
function buildEntityLabelContextDraft(draft: FeatureCollection, entities: Entity[]): FeatureCollection {
if (!draft.features.length) return draft;
const entityById = new globalThis.Map<string, Entity>();
for (const entity of entities || []) {
const id = String(entity?.id || "").trim();
if (!id) continue;
entityById.set(id, entity);
}
return {
...draft,
features: draft.features.map((feature) => {
const entityIds = normalizeFeatureEntityIds(feature);
if (!entityIds.length) return feature;
const candidates = entityIds.map((id) => {
const entity = entityById.get(id) || null;
const name = String(entity?.name || id).trim();
if (!name) return null;
return {
id,
name,
time_start: normalizeTimelineYearValue(entity?.time_start),
time_end: normalizeTimelineYearValue(entity?.time_end),
};
}).filter((candidate) => candidate !== null);
return {
...feature,
properties: {
...feature.properties,
entity_id: entityIds[0] || null,
entity_ids: entityIds,
entity_name: candidates[0]?.name || null,
entity_names: candidates.map((candidate) => candidate.name),
entity_label_candidates: candidates,
},
};
}),
};
}
function buildEntityRefsForFeature(feature: Feature, entities: Entity[]): Entity[] {
const entityIds = normalizeFeatureEntityIds(feature);
if (!entityIds.length) return [];