add type
This commit is contained in:
@@ -12,7 +12,7 @@ Nguồn tham chiếu trong code:
|
||||
Snapshot hiện tại:
|
||||
|
||||
- Không có `schema_version`.
|
||||
- Không lưu `section` (project/section được xác định bằng context record `commits.project_id`).
|
||||
- Không lưu `section` (entity trong DB là `projects`; project được xác định bằng context record `commits.project_id`).
|
||||
- Không dùng `ref:{id}` nữa: **`id` là canonical**, `source:"ref"` nghĩa là tham chiếu theo `id`.
|
||||
|
||||
```ts
|
||||
@@ -28,6 +28,130 @@ export type CommitSnapshot = {
|
||||
};
|
||||
```
|
||||
|
||||
## 1.1 Type đầy đủ (TypeScript)
|
||||
|
||||
Đây là bản type "đúng để BEGo implement chuyển đổi snapshot → DB". FE có thể gửi thêm field legacy (xem mục 6), nhưng BE nên normalize theo các type dưới đây.
|
||||
|
||||
```ts
|
||||
// ---- GeoJSON ----
|
||||
|
||||
export type Geometry =
|
||||
| { type: "Point"; coordinates: [number, number] }
|
||||
| { type: "MultiPoint"; coordinates: [number, number][] }
|
||||
| { type: "LineString"; coordinates: [number, number][] }
|
||||
| { type: "MultiLineString"; coordinates: [number, number][][] }
|
||||
| { type: "Polygon"; coordinates: [number, number][][] }
|
||||
| { type: "MultiPolygon"; coordinates: [number, number][][][] };
|
||||
|
||||
export type FeatureId = string | number; // FE hiện dùng UUIDv7 string
|
||||
|
||||
export type FeatureProperties = {
|
||||
id: FeatureId;
|
||||
type?: string | null;
|
||||
geometry_preset?: string | null;
|
||||
time_start?: number | null;
|
||||
time_end?: number | null;
|
||||
binding?: string[]; // entity ids used as "binding filter"
|
||||
|
||||
// Legacy UI fields. FE persist snapshot hiện tại KHONG gửi các field này,
|
||||
// nhưng BE nên ignore nếu gặp trong snapshot cũ:
|
||||
entity_id?: string | null;
|
||||
entity_ids?: string[];
|
||||
entity_name?: string | null;
|
||||
entity_names?: string[];
|
||||
entity_type_id?: string | null;
|
||||
};
|
||||
|
||||
export type Feature = {
|
||||
type: "Feature";
|
||||
properties: FeatureProperties;
|
||||
geometry: Geometry;
|
||||
};
|
||||
|
||||
export type FeatureCollection = {
|
||||
type: "FeatureCollection";
|
||||
features: Feature[];
|
||||
};
|
||||
|
||||
// ---- Snapshot rows ----
|
||||
|
||||
export type SnapshotSource = "inline" | "ref";
|
||||
|
||||
export type EntitySnapshotOperation = "create" | "update" | "delete" | "reference";
|
||||
export type GeometrySnapshotOperation = "create" | "update" | "delete" | "reference";
|
||||
export type WikiSnapshotOperation = "create" | "update" | "delete" | "reference";
|
||||
|
||||
export type EntitySnapshot = {
|
||||
id: string; // UUIDv7 string (canonical)
|
||||
source: SnapshotSource;
|
||||
operation?: EntitySnapshotOperation;
|
||||
name?: string;
|
||||
slug?: string | null;
|
||||
description?: string | null;
|
||||
type_id?: string | null;
|
||||
status?: number | null;
|
||||
base_updated_at?: string;
|
||||
base_hash?: string;
|
||||
};
|
||||
|
||||
export type GeometrySnapshot = {
|
||||
id: string; // UUIDv7 string (canonical)
|
||||
source: SnapshotSource;
|
||||
operation?: GeometrySnapshotOperation;
|
||||
|
||||
// Present when source:"inline" (draft features)
|
||||
type?: string | null;
|
||||
draw_geometry?: Geometry;
|
||||
binding?: string[];
|
||||
time_start?: number | null;
|
||||
time_end?: number | null;
|
||||
bbox?: {
|
||||
min_lng: number;
|
||||
min_lat: number;
|
||||
max_lng: number;
|
||||
max_lat: number;
|
||||
} | null;
|
||||
|
||||
base_updated_at?: string;
|
||||
base_hash?: string;
|
||||
};
|
||||
|
||||
export type WikiSnapshot = {
|
||||
id: string; // UUIDv7 string (canonical)
|
||||
source: SnapshotSource;
|
||||
operation?: WikiSnapshotOperation;
|
||||
title: string;
|
||||
doc: unknown; // tiptap JSON (inline) hoặc null (ref)
|
||||
updated_at?: string;
|
||||
};
|
||||
|
||||
// ---- Join tables ----
|
||||
|
||||
export type GeometryEntitySnapshot = {
|
||||
geometry_id: string;
|
||||
entity_id: string;
|
||||
base_links_hash?: string;
|
||||
};
|
||||
|
||||
export type EntityWikiLinkSnapshot = {
|
||||
entity_id: string;
|
||||
wiki_id: string;
|
||||
// If missing, BE should treat as "reference" (active link) for backwards-compat.
|
||||
operation?: "reference" | "delete";
|
||||
};
|
||||
|
||||
// ---- Root ----
|
||||
|
||||
export type CommitSnapshot = {
|
||||
editor_feature_collection?: FeatureCollection;
|
||||
entities?: EntitySnapshot[];
|
||||
geometries?: GeometrySnapshot[];
|
||||
wikis?: WikiSnapshot[];
|
||||
geometry_entity?: GeometryEntitySnapshot[];
|
||||
entity_wiki?: EntityWikiLinkSnapshot[];
|
||||
};
|
||||
```
|
||||
|
||||
## 2) Quy Ước `source` và `operation`
|
||||
|
||||
### 2.1 `source` (bắt buộc)
|
||||
@@ -113,6 +237,11 @@ Nếu feature bị xoá khỏi draft, FE thêm 1 delete row:
|
||||
|
||||
Lưu ý: geometry `operation:"delete"` **không xuất hiện trên map**, vì map render theo `editor_feature_collection.features[]`.
|
||||
|
||||
Gợi ý cho BE khi apply vào DB:
|
||||
|
||||
- Có thể coi `editor_feature_collection` là state hiện tại để render/map.
|
||||
- `geometries[]` là "rows + deltas": sẽ có 1 row cho mỗi feature đang tồn tại trong draft (có/không có `operation`), và có thể có thêm các row `operation:"delete"` để xoá geometry khỏi project state.
|
||||
|
||||
### 3.4 `geometry_entity[]` (join table Geometry ↔ Entity)
|
||||
|
||||
Join table many-to-many giữa geometry và entity. Mỗi cặp geometry↔entity là một row:
|
||||
@@ -206,3 +335,21 @@ Toggle link trong UI:
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 5) Notes Cho BackEnd (Normalize + Compat)
|
||||
|
||||
BE nên normalize trước khi convert snapshot → DB:
|
||||
|
||||
- Ignore toàn bộ field entity denormalize trên `feature.properties` (nếu có): `entity_id/entity_ids/entity_name/entity_names/entity_type_id`. Quan hệ geometry↔entity lấy từ `geometry_entity[]`.
|
||||
- `entity_wiki[].operation`:
|
||||
- `"reference"`: link active
|
||||
- `"delete"`: link removed trong snapshot
|
||||
- missing: treat as `"reference"` (compat)
|
||||
|
||||
## 6) Legacy Compatibility (nếu gặp snapshot cũ)
|
||||
|
||||
FE đã từng gửi các field legacy; BE có thể gặp nếu đang xử lý commit cũ:
|
||||
|
||||
- `entity_wikis` (plural) thay vì `entity_wiki` (singular): treat như nhau.
|
||||
- `ref:{id}` trong `entities/geometries/wikis`: ignore (id canonical).
|
||||
- `is_deleted` trong join table entity↔wiki: map sang `operation:"delete"` khi `is_deleted==1`, ngược lại `"reference"`.
|
||||
|
||||
@@ -8,19 +8,18 @@ export type EntityWikiLinkSnapshot = {
|
||||
operation?: "reference" | "delete";
|
||||
};
|
||||
|
||||
// API mới (BackEndGo) dùng Projects/Commits/Submissions.
|
||||
// Giữ tên type "Section" để tránh thay đổi lan rộng trong FE hiện tại.
|
||||
export type SectionStatus = string;
|
||||
export type SectionSubmissionStatus = "PENDING" | "APPROVED" | "REJECTED" | string;
|
||||
// BackEndGo uses Projects/Commits/Submissions. "Section" is legacy naming in FE.
|
||||
export type ProjectStatus = string;
|
||||
export type ProjectSubmissionStatus = "PENDING" | "APPROVED" | "REJECTED" | string;
|
||||
|
||||
export type SectionState = {
|
||||
export type ProjectState = {
|
||||
// Derived state from ProjectResponse (not persisted as-is in API mới).
|
||||
status: SectionStatus;
|
||||
status: ProjectStatus;
|
||||
head_commit_id: string | null;
|
||||
locked_by?: string | null;
|
||||
};
|
||||
|
||||
export type Section = {
|
||||
export type Project = {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string | null;
|
||||
@@ -36,7 +35,7 @@ export type Section = {
|
||||
};
|
||||
};
|
||||
|
||||
export type SectionCommit = {
|
||||
export type ProjectCommit = {
|
||||
id: string;
|
||||
project_id: string;
|
||||
snapshot_json: EditorSnapshot;
|
||||
@@ -46,13 +45,13 @@ export type SectionCommit = {
|
||||
created_at?: string;
|
||||
};
|
||||
|
||||
export type SectionSubmission = {
|
||||
export type ProjectSubmission = {
|
||||
id: string;
|
||||
project_id: string;
|
||||
commit_id: string;
|
||||
user_id: string;
|
||||
created_at?: string;
|
||||
status: SectionSubmissionStatus;
|
||||
status: ProjectSubmissionStatus;
|
||||
reviewed_by?: string | null;
|
||||
reviewed_at?: string | null;
|
||||
review_note?: string | null;
|
||||
@@ -75,10 +74,13 @@ export type EditorSnapshot = {
|
||||
entity_wiki?: EntityWikiLinkSnapshot[];
|
||||
};
|
||||
|
||||
// Alias for clearer naming at API boundary: commits.snapshot_json is this shape.
|
||||
export type CommitSnapshot = EditorSnapshot;
|
||||
|
||||
export type EditorLoadResponse = {
|
||||
section: Section;
|
||||
state: SectionState;
|
||||
commit: SectionCommit | null;
|
||||
section: Project;
|
||||
state: ProjectState;
|
||||
commit: ProjectCommit | null;
|
||||
snapshot: EditorSnapshot | null;
|
||||
};
|
||||
|
||||
@@ -96,3 +98,11 @@ export type CreateCommitInput = {
|
||||
export type RestoreCommitInput = {
|
||||
commit_id: string;
|
||||
};
|
||||
|
||||
// Legacy aliases (to reduce churn in existing FE code). Prefer Project* names above.
|
||||
export type SectionStatus = ProjectStatus;
|
||||
export type SectionSubmissionStatus = ProjectSubmissionStatus;
|
||||
export type SectionState = ProjectState;
|
||||
export type Section = Project;
|
||||
export type SectionCommit = ProjectCommit;
|
||||
export type SectionSubmission = ProjectSubmission;
|
||||
|
||||
Reference in New Issue
Block a user