refactor: rename entity type configuration to geometry type and relocate to dedicated map utilities.
This commit is contained in:
@@ -31,8 +31,8 @@ import {
|
|||||||
HIDDEN_BACKGROUND_LAYER_VISIBILITY,
|
HIDDEN_BACKGROUND_LAYER_VISIBILITY,
|
||||||
} from "@/uhm/lib/map/styles/backgroundLayers";
|
} from "@/uhm/lib/map/styles/backgroundLayers";
|
||||||
import {
|
import {
|
||||||
ENTITY_TYPE_OPTIONS,
|
GEOMETRY_TYPE_OPTIONS,
|
||||||
} from "@/uhm/lib/utils/entityTypeOptions";
|
} from "@/uhm/lib/map/geo/geometryTypeOptions";
|
||||||
import {
|
import {
|
||||||
EntityFormState,
|
EntityFormState,
|
||||||
GeometryMetaFormState,
|
GeometryMetaFormState,
|
||||||
@@ -1560,7 +1560,7 @@ export default function Page() {
|
|||||||
entities={entities}
|
entities={entities}
|
||||||
selectedGeometryEntityIds={selectedGeometryEntityIds}
|
selectedGeometryEntityIds={selectedGeometryEntityIds}
|
||||||
onEntityIdsChange={handleEntityIdsChange}
|
onEntityIdsChange={handleEntityIdsChange}
|
||||||
entityTypeOptions={ENTITY_TYPE_OPTIONS}
|
entityTypeOptions={GEOMETRY_TYPE_OPTIONS}
|
||||||
geometryMetaForm={geometryMetaForm}
|
geometryMetaForm={geometryMetaForm}
|
||||||
onGeometryMetaFormChange={handleGeometryMetaFormChange}
|
onGeometryMetaFormChange={handleGeometryMetaFormChange}
|
||||||
isEntitySubmitting={isEntitySubmitting}
|
isEntitySubmitting={isEntitySubmitting}
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import { type CSSProperties, useMemo, useState } from "react";
|
|||||||
import { Entity } from "@/uhm/api/entities";
|
import { Entity } from "@/uhm/api/entities";
|
||||||
import { Feature } from "@/uhm/lib/editor/state/useEditorState";
|
import { Feature } from "@/uhm/lib/editor/state/useEditorState";
|
||||||
import {
|
import {
|
||||||
EntityGeometryPreset,
|
GeometryPreset,
|
||||||
EntityTypeGroupId,
|
GeometryTypeGroupId,
|
||||||
EntityTypeOption,
|
GeometryTypeOption,
|
||||||
findEntityTypeOption,
|
findGeometryTypeOption,
|
||||||
groupEntityTypeOptions,
|
groupGeometryTypeOptions,
|
||||||
} from "@/uhm/lib/utils/entityTypeOptions";
|
} from "@/uhm/lib/map/geo/geometryTypeOptions";
|
||||||
import type { GeometryMetaFormState } from "@/uhm/lib/editor/session/sessionTypes";
|
import type { GeometryMetaFormState } from "@/uhm/lib/editor/session/sessionTypes";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -19,7 +19,7 @@ type Props = {
|
|||||||
entities: Entity[];
|
entities: Entity[];
|
||||||
selectedGeometryEntityIds: string[];
|
selectedGeometryEntityIds: string[];
|
||||||
onEntityIdsChange: (values: string[]) => void;
|
onEntityIdsChange: (values: string[]) => void;
|
||||||
entityTypeOptions: EntityTypeOption[];
|
entityTypeOptions: GeometryTypeOption[];
|
||||||
geometryMetaForm: GeometryMetaFormState;
|
geometryMetaForm: GeometryMetaFormState;
|
||||||
onGeometryMetaFormChange: (key: keyof GeometryMetaFormState, value: string) => void;
|
onGeometryMetaFormChange: (key: keyof GeometryMetaFormState, value: string) => void;
|
||||||
isEntitySubmitting: boolean;
|
isEntitySubmitting: boolean;
|
||||||
@@ -81,13 +81,13 @@ export default function SelectedGeometryPanel({
|
|||||||
if (!selectedFeatures || selectedFeatures.length === 0) return null;
|
if (!selectedFeatures || selectedFeatures.length === 0) return null;
|
||||||
const representativeFeature = selectedFeatures[0];
|
const representativeFeature = selectedFeatures[0];
|
||||||
|
|
||||||
const groupedEntityTypeOptions = groupEntityTypeOptions(entityTypeOptions);
|
const groupedGeometryTypeOptions = groupGeometryTypeOptions(entityTypeOptions);
|
||||||
const featureGeometryPreset = resolveFeatureGeometryPreset(representativeFeature);
|
const featureGeometryPreset = resolveFeatureGeometryPreset(representativeFeature);
|
||||||
const allowedGroupIds = getAllowedGroupIdsForPreset(featureGeometryPreset);
|
const allowedGroupIds = getAllowedGroupIdsForPreset(featureGeometryPreset);
|
||||||
const groupedGeoTypeOptions = groupedEntityTypeOptions.filter((group) =>
|
const groupedGeoTypeOptions = groupedGeometryTypeOptions.filter((group) =>
|
||||||
allowedGroupIds.includes(group.id)
|
allowedGroupIds.includes(group.id)
|
||||||
);
|
);
|
||||||
const selectedTypeOption = findEntityTypeOption(geometryMetaForm.type_key);
|
const selectedTypeOption = findGeometryTypeOption(geometryMetaForm.type_key);
|
||||||
const hasCurrentVisibleTypeOption = groupedGeoTypeOptions.some((group) =>
|
const hasCurrentVisibleTypeOption = groupedGeoTypeOptions.some((group) =>
|
||||||
group.options.some((option) => option.value === geometryMetaForm.type_key)
|
group.options.some((option) => option.value === geometryMetaForm.type_key)
|
||||||
);
|
);
|
||||||
@@ -342,20 +342,20 @@ function MinusIcon() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveFeatureGeometryPreset(feature: Feature): EntityGeometryPreset {
|
function resolveFeatureGeometryPreset(feature: Feature): GeometryPreset {
|
||||||
const explicitPreset = normalizeGeometryPreset(feature.properties.geometry_preset);
|
const explicitPreset = normalizeGeometryPreset(feature.properties.geometry_preset);
|
||||||
if (explicitPreset) return explicitPreset;
|
if (explicitPreset) return explicitPreset;
|
||||||
|
|
||||||
const semanticType = normalizeTypeId(feature.properties.type) || normalizeTypeId(feature.properties.entity_type_id);
|
const semanticType = normalizeTypeId(feature.properties.type) || normalizeTypeId(feature.properties.entity_type_id);
|
||||||
if (semanticType) {
|
if (semanticType) {
|
||||||
const option = findEntityTypeOption(semanticType);
|
const option = findGeometryTypeOption(semanticType);
|
||||||
if (option) return option.geometryPreset;
|
if (option) return option.geometryPreset;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapGeometryTypeToPreset(feature.geometry.type);
|
return mapGeometryTypeToPreset(feature.geometry.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeGeometryPreset(value: unknown): EntityGeometryPreset | null {
|
function normalizeGeometryPreset(value: unknown): GeometryPreset | null {
|
||||||
if (typeof value !== "string") return null;
|
if (typeof value !== "string") return null;
|
||||||
const normalized = value.trim().toLowerCase();
|
const normalized = value.trim().toLowerCase();
|
||||||
if (
|
if (
|
||||||
@@ -377,7 +377,7 @@ function normalizeTypeId(value: unknown): string | null {
|
|||||||
|
|
||||||
function mapGeometryTypeToPreset(
|
function mapGeometryTypeToPreset(
|
||||||
geometryType: Feature["geometry"]["type"]
|
geometryType: Feature["geometry"]["type"]
|
||||||
): EntityGeometryPreset {
|
): GeometryPreset {
|
||||||
if (geometryType === "Point" || geometryType === "MultiPoint") {
|
if (geometryType === "Point" || geometryType === "MultiPoint") {
|
||||||
return "point";
|
return "point";
|
||||||
}
|
}
|
||||||
@@ -388,8 +388,8 @@ function mapGeometryTypeToPreset(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getAllowedGroupIdsForPreset(
|
function getAllowedGroupIdsForPreset(
|
||||||
geometryPreset: EntityGeometryPreset
|
geometryPreset: GeometryPreset
|
||||||
): EntityTypeGroupId[] {
|
): GeometryTypeGroupId[] {
|
||||||
if (geometryPreset === "point") {
|
if (geometryPreset === "point") {
|
||||||
return ["point"];
|
return ["point"];
|
||||||
}
|
}
|
||||||
@@ -405,7 +405,7 @@ function getAllowedGroupIdsForPreset(
|
|||||||
return ["polygon"];
|
return ["polygon"];
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatGeometryPresetLabel(preset: EntityGeometryPreset | null): string {
|
function formatGeometryPresetLabel(preset: GeometryPreset | null): string {
|
||||||
if (preset === "point") return "point - Điểm";
|
if (preset === "point") return "point - Điểm";
|
||||||
if (preset === "line") return "line - Tuyến";
|
if (preset === "line") return "line - Tuyến";
|
||||||
if (preset === "circle-area") return "circle - Tròn";
|
if (preset === "circle-area") return "circle - Tròn";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { EntityGeometryPreset } from "@/uhm/lib/utils/entityTypeOptions";
|
import type { GeometryPreset } from "@/uhm/lib/map/geo/geometryTypeOptions";
|
||||||
|
|
||||||
export type EditorMode =
|
export type EditorMode =
|
||||||
| "idle"
|
| "idle"
|
||||||
@@ -38,4 +38,4 @@ export type CreatedEntitySummary = {
|
|||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GeometryPreset = EntityGeometryPreset;
|
export type { GeometryPreset };
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DEFAULT_ENTITY_TYPE_ID } from "@/uhm/lib/utils/entityTypeOptions";
|
import { DEFAULT_GEOMETRY_TYPE_ID } from "@/uhm/lib/map/geo/geometryTypeOptions";
|
||||||
import { geoTypeCodeToTypeKey, typeKeyToGeoTypeCode } from "@/uhm/lib/map/geo/geoTypeMap";
|
import { geoTypeCodeToTypeKey, typeKeyToGeoTypeCode } from "@/uhm/lib/map/geo/geoTypeMap";
|
||||||
import type { Change } from "@/uhm/lib/editor/draft/editorTypes";
|
import type { Change } from "@/uhm/lib/editor/draft/editorTypes";
|
||||||
import type { EntitySnapshot } from "@/uhm/types/entities";
|
import type { EntitySnapshot } from "@/uhm/types/entities";
|
||||||
@@ -659,7 +659,7 @@ export function getDefaultTypeIdForFeature(feature: Feature): string {
|
|||||||
if (preset === "line") return "defense_line";
|
if (preset === "line") return "defense_line";
|
||||||
if (preset === "point") return "city";
|
if (preset === "point") return "city";
|
||||||
if (preset === "circle-area") return "war";
|
if (preset === "circle-area") return "war";
|
||||||
if (preset === "polygon") return DEFAULT_ENTITY_TYPE_ID;
|
if (preset === "polygon") return DEFAULT_GEOMETRY_TYPE_ID;
|
||||||
|
|
||||||
const geometryType = feature.geometry.type;
|
const geometryType = feature.geometry.type;
|
||||||
if (geometryType === "LineString" || geometryType === "MultiLineString") {
|
if (geometryType === "LineString" || geometryType === "MultiLineString") {
|
||||||
@@ -668,7 +668,7 @@ export function getDefaultTypeIdForFeature(feature: Feature): string {
|
|||||||
if (geometryType === "Point" || geometryType === "MultiPoint") {
|
if (geometryType === "Point" || geometryType === "MultiPoint") {
|
||||||
return "city";
|
return "city";
|
||||||
}
|
}
|
||||||
return DEFAULT_ENTITY_TYPE_ID;
|
return DEFAULT_GEOMETRY_TYPE_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalizeFeatureEntityIds(feature: Feature): string[] {
|
export function normalizeFeatureEntityIds(feature: Feature): string[] {
|
||||||
|
|||||||
+24
-24
@@ -1,27 +1,27 @@
|
|||||||
export type EntityTypeGroupId =
|
export type GeometryTypeGroupId =
|
||||||
| "line"
|
| "line"
|
||||||
| "polygon"
|
| "polygon"
|
||||||
| "circle"
|
| "circle"
|
||||||
| "point";
|
| "point";
|
||||||
|
|
||||||
export type EntityGeometryPreset = "line" | "polygon" | "circle-area" | "point";
|
export type GeometryPreset = "line" | "polygon" | "circle-area" | "point";
|
||||||
|
|
||||||
export type EntityTypeGroup = {
|
export type GeometryTypeGroup = {
|
||||||
id: EntityTypeGroupId;
|
id: GeometryTypeGroupId;
|
||||||
label: string;
|
label: string;
|
||||||
geometryLabel: string;
|
geometryLabel: string;
|
||||||
description: string;
|
description: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type EntityTypeOption = {
|
export type GeometryTypeOption = {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
groupId: EntityTypeGroupId;
|
groupId: GeometryTypeGroupId;
|
||||||
groupLabel: string;
|
groupLabel: string;
|
||||||
geometryPreset: EntityGeometryPreset;
|
geometryPreset: GeometryPreset;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ENTITY_TYPE_GROUPS: EntityTypeGroup[] = [
|
export const GEOMETRY_TYPE_GROUPS: GeometryTypeGroup[] = [
|
||||||
{
|
{
|
||||||
id: "line",
|
id: "line",
|
||||||
label: "line - Tuyến",
|
label: "line - Tuyến",
|
||||||
@@ -48,18 +48,18 @@ export const ENTITY_TYPE_GROUPS: EntityTypeGroup[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const GROUP_BY_ID: Record<EntityTypeGroupId, EntityTypeGroup> = {
|
const GROUP_BY_ID: Record<GeometryTypeGroupId, GeometryTypeGroup> = {
|
||||||
line: ENTITY_TYPE_GROUPS[0],
|
line: GEOMETRY_TYPE_GROUPS[0],
|
||||||
polygon: ENTITY_TYPE_GROUPS[1],
|
polygon: GEOMETRY_TYPE_GROUPS[1],
|
||||||
circle: ENTITY_TYPE_GROUPS[2],
|
circle: GEOMETRY_TYPE_GROUPS[2],
|
||||||
point: ENTITY_TYPE_GROUPS[3],
|
point: GEOMETRY_TYPE_GROUPS[3],
|
||||||
};
|
};
|
||||||
|
|
||||||
const RAW_ENTITY_TYPE_OPTIONS: Array<{
|
const RAW_GEOMETRY_TYPE_OPTIONS: Array<{
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
groupId: EntityTypeGroupId;
|
groupId: GeometryTypeGroupId;
|
||||||
geometryPreset: EntityGeometryPreset;
|
geometryPreset: GeometryPreset;
|
||||||
}> = [
|
}> = [
|
||||||
{ value: "defense_line", label: "Defense Line", groupId: "line", geometryPreset: "line" },
|
{ value: "defense_line", label: "Defense Line", groupId: "line", geometryPreset: "line" },
|
||||||
|
|
||||||
@@ -94,29 +94,29 @@ const RAW_ENTITY_TYPE_OPTIONS: Array<{
|
|||||||
{ value: "bridge", label: "Bridge", groupId: "point", geometryPreset: "point" },
|
{ value: "bridge", label: "Bridge", groupId: "point", geometryPreset: "point" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ENTITY_TYPE_OPTIONS: EntityTypeOption[] = RAW_ENTITY_TYPE_OPTIONS.map((item) => ({
|
export const GEOMETRY_TYPE_OPTIONS: GeometryTypeOption[] = RAW_GEOMETRY_TYPE_OPTIONS.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
groupLabel: GROUP_BY_ID[item.groupId].label,
|
groupLabel: GROUP_BY_ID[item.groupId].label,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const DEFAULT_ENTITY_TYPE_ID = "country";
|
export const DEFAULT_GEOMETRY_TYPE_ID = "country";
|
||||||
|
|
||||||
// Gom option theo group để render select phân nhóm.
|
// Gom option theo group để render select phân nhóm.
|
||||||
export function groupEntityTypeOptions(options: EntityTypeOption[] = ENTITY_TYPE_OPTIONS): Array<{
|
export function groupGeometryTypeOptions(options: GeometryTypeOption[] = GEOMETRY_TYPE_OPTIONS): Array<{
|
||||||
id: EntityTypeGroupId;
|
id: GeometryTypeGroupId;
|
||||||
label: string;
|
label: string;
|
||||||
geometryLabel: string;
|
geometryLabel: string;
|
||||||
description: string;
|
description: string;
|
||||||
options: EntityTypeOption[];
|
options: GeometryTypeOption[];
|
||||||
}> {
|
}> {
|
||||||
return ENTITY_TYPE_GROUPS.map((group) => ({
|
return GEOMETRY_TYPE_GROUPS.map((group) => ({
|
||||||
...group,
|
...group,
|
||||||
options: options.filter((option) => option.groupId === group.id),
|
options: options.filter((option) => option.groupId === group.id),
|
||||||
})).filter((group) => group.options.length > 0);
|
})).filter((group) => group.options.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tìm option theo type id, trả null nếu không tồn tại.
|
// Tìm option theo type id, trả null nếu không tồn tại.
|
||||||
export function findEntityTypeOption(typeId: string | null | undefined): EntityTypeOption | null {
|
export function findGeometryTypeOption(typeId: string | null | undefined): GeometryTypeOption | null {
|
||||||
if (!typeId) return null;
|
if (!typeId) return null;
|
||||||
return ENTITY_TYPE_OPTIONS.find((option) => option.value === typeId) || null;
|
return GEOMETRY_TYPE_OPTIONS.find((option) => option.value === typeId) || null;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { EntityGeometryPreset } from "@/uhm/lib/utils/entityTypeOptions";
|
import type { GeometryPreset } from "@/uhm/lib/map/geo/geometryTypeOptions";
|
||||||
|
|
||||||
export type Geometry =
|
export type Geometry =
|
||||||
| { type: "Point"; coordinates: [number, number] }
|
| { type: "Point"; coordinates: [number, number] }
|
||||||
@@ -13,7 +13,7 @@ export type FeatureId = string | number;
|
|||||||
export type FeatureProperties = {
|
export type FeatureProperties = {
|
||||||
id: FeatureId;
|
id: FeatureId;
|
||||||
type?: string | null;
|
type?: string | null;
|
||||||
geometry_preset?: EntityGeometryPreset | null;
|
geometry_preset?: GeometryPreset | null;
|
||||||
time_start?: number | null;
|
time_start?: number | null;
|
||||||
time_end?: number | null;
|
time_end?: number | null;
|
||||||
binding?: string[];
|
binding?: string[];
|
||||||
|
|||||||
Reference in New Issue
Block a user