feat: Support multi-select editor workflow and improve UI/UX
- Refactored state from single selectedFeatureId to selectedFeatureIds array in Editor and Viewer - Updated Map component to support multi-select filtering for geometry binding visibility - Made entity, wiki, and geometry side panels scrollable for better overflow handling - Fixed viewer mode wiki link navigation for independent wikis - Improved geometry binding UX and state synchronization
This commit is contained in:
@@ -46,7 +46,7 @@ type Options = {
|
||||
setSnapshotEntities: Dispatch<SetStateAction<EntitySnapshot[]>>;
|
||||
setSnapshotWikis: Dispatch<SetStateAction<WikiSnapshot[]>>;
|
||||
setSnapshotEntityWikiLinks: Dispatch<SetStateAction<EntityWikiLinkSnapshot[]>>;
|
||||
setSelectedFeatureId: Dispatch<SetStateAction<FeatureId | null>>;
|
||||
setSelectedFeatureIds: Dispatch<SetStateAction<FeatureId[]>>;
|
||||
setEntityFormStatus: Dispatch<SetStateAction<string | null>>;
|
||||
setEntityStatus: Dispatch<SetStateAction<string | null>>;
|
||||
setIsSaving: Dispatch<SetStateAction<boolean>>;
|
||||
@@ -76,7 +76,7 @@ export function useSectionCommands(options: Options) {
|
||||
options.setSnapshotEntities(sessionSnapshot?.entities || []);
|
||||
options.setSnapshotWikis(sessionSnapshot?.wikis || []);
|
||||
options.setSnapshotEntityWikiLinks(sessionSnapshot?.entity_wiki || []);
|
||||
options.setSelectedFeatureId(null);
|
||||
options.setSelectedFeatureIds([]);
|
||||
options.setEntityFormStatus(null);
|
||||
}, [options]);
|
||||
|
||||
@@ -271,7 +271,7 @@ export function useSectionCommands(options: Options) {
|
||||
options.setSnapshotEntities(sessionSnapshot?.entities || []);
|
||||
options.setSnapshotWikis(sessionSnapshot?.wikis || []);
|
||||
options.setSnapshotEntityWikiLinks(sessionSnapshot?.entity_wiki || []);
|
||||
options.setSelectedFeatureId(null);
|
||||
options.setSelectedFeatureIds([]);
|
||||
options.setEntityFormStatus(null);
|
||||
|
||||
// Refresh commits list for UI, but keep sectionState/head as-is.
|
||||
|
||||
@@ -14,8 +14,8 @@ export function useEntitySessionState() {
|
||||
const [snapshotEntities, setSnapshotEntities] = useState<EntitySnapshot[]>([]);
|
||||
// Thông báo trạng thái/lỗi liên quan entity/session.
|
||||
const [entityStatus, setEntityStatus] = useState<string | null>(null);
|
||||
// Feature đang được chọn để thao tác bind entities/metadata.
|
||||
const [selectedFeatureId, setSelectedFeatureId] = useState<FeatureId | null>(null);
|
||||
// Features đang được chọn để thao tác bind entities/metadata.
|
||||
const [selectedFeatureIds, setSelectedFeatureIds] = useState<FeatureId[]>([]);
|
||||
// Form tạo entity mới (độc lập).
|
||||
const [entityForm, setEntityForm] = useState<EntityFormState>({
|
||||
name: "",
|
||||
@@ -50,8 +50,8 @@ export function useEntitySessionState() {
|
||||
setSnapshotEntities,
|
||||
entityStatus,
|
||||
setEntityStatus,
|
||||
selectedFeatureId,
|
||||
setSelectedFeatureId,
|
||||
selectedFeatureIds,
|
||||
setSelectedFeatureIds,
|
||||
entityForm,
|
||||
setEntityForm,
|
||||
selectedGeometryEntityIds,
|
||||
|
||||
@@ -7,7 +7,7 @@ export function initSelect(
|
||||
getMode: ModeGetter,
|
||||
onDelete?: (id: string | number) => void,
|
||||
onEdit?: (feature: maplibregl.MapGeoJSONFeature) => void,
|
||||
onSelectId?: (id: string | number | null) => void
|
||||
onSelectIds?: (ids: (string | number)[]) => void
|
||||
) {
|
||||
const SELECTABLE_LAYERS = [
|
||||
"countries-fill",
|
||||
@@ -35,7 +35,7 @@ export function initSelect(
|
||||
selectedIds.forEach((id) => setSelectionStateForId(id, false));
|
||||
selectedIds.clear();
|
||||
if (emit) {
|
||||
onSelectId?.(null);
|
||||
onSelectIds?.([]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,13 +52,13 @@ export function initSelect(
|
||||
// Alt + click on an already selected feature removes it from the selection
|
||||
setSelectionStateForId(id, false);
|
||||
selectedIds.delete(id);
|
||||
onSelectId?.(selectedIds.size === 1 ? Array.from(selectedIds)[0] : null);
|
||||
onSelectIds?.(Array.from(selectedIds));
|
||||
return;
|
||||
}
|
||||
|
||||
setSelectionStateForId(id, true);
|
||||
selectedIds.add(id);
|
||||
onSelectId?.(selectedIds.size === 1 ? id : null);
|
||||
onSelectIds?.(Array.from(selectedIds));
|
||||
}
|
||||
|
||||
// Chọn feature theo click trái, hỗ trợ additive bằng Alt.
|
||||
|
||||
@@ -61,7 +61,8 @@ export function snapToNearestGeometry(
|
||||
}
|
||||
|
||||
const type = feature.geometry.type;
|
||||
const coords = feature.geometry.coordinates as any;
|
||||
if (type === "GeometryCollection") continue;
|
||||
const coords = (feature.geometry as any).coordinates;
|
||||
|
||||
// Xử lý cả Polygon và LineString vì viền bản đồ (border) đôi khi được render dưới dạng LineString
|
||||
if (type === "Polygon") {
|
||||
|
||||
Reference in New Issue
Block a user