7.7 KiB
UHM Editor - state và vòng đời dữ liệu
Tài liệu này mô tả state thật đang được dùng bởi editor hiện tại.
Entry point chính là useEditorSessionState() và useEditorState().
1. Hai lớp state chính
Editor đang tách làm hai khối:
useEditorSessionState()- state UI, session, form, project, timeline, background, wiki
useEditorState(initialData, snapshotUndo)- state draft hình học, diff và undo
Nói ngắn gọn:
session statequyết định editor đang nhìn cái gì và panel đang thao tác gìeditor statequyết định geometry nào đang tồn tại trong draft và khác baseline ra sao
2. State geometry trung tâm
initialData
- Nằm ở
useEditorSessionState() - Là
FeatureCollectionđang được nạp vào editor khi mở project hoặc restore commit - Khi thay đổi,
useEditorState()sẽ reset toàn bộ draft và baseline tương ứng
draft
- Nằm trong
useEditorState() - Là nguồn dữ liệu render trực tiếp cho
Map - Mọi thao tác create/update/delete geometry đều đi qua đây
draftRef
- Bản ref của
draft - Được dùng trong event handlers của map engine để luôn đọc được state mới nhất mà không phải rebind callback liên tục
initialMapRef
Map<featureId, Feature>tạo từinitialData- Là baseline để tính diff giữa draft hiện tại và dữ liệu gốc của session
changes
- Kết quả
diffDraftToInitial(draft, initialMapRef.current) - Map theo
feature.properties.id - Mỗi phần tử có thể là:
createupdatedelete
Lưu ý: diff hiện chỉ là cơ chế nhận biết geometry nào đã thay đổi so với baseline. Snapshot commit thực tế vẫn được build từ toàn bộ draft cộng với các snapshot bảng phụ.
changeCount
- Số lượng geometry thay đổi hiện tại
- Được cộng thêm dirty state của wiki/entity/entity-wiki để tạo
pendingSaveCount
3. Undo state
Undo được quản lý bởi useUndoStack().
Kiểu action hiện có:
createdeleteupdatepropertiessnapshot_entitiessnapshot_wikissnapshot_entity_wikigroup
Ý nghĩa:
- geometry create/delete/update/properties undo được trực tiếp trên
draft - snapshot entity/wiki/link undo được apply qua
snapshotUndoAPI truyền vàouseEditorState groupdùng để gom nhiều thay đổi thành một thao tác undo logic
Editor hiện có undo, nhưng chưa có redo.
4. Session state theo nhóm
4.1. Mode và selection
mode: EditorModeselectedFeatureIdsselectedGeometryEntityIds
selectedFeatureIds là state gốc cho:
- panel metadata geometry
- bind entity
- bind geometry
- focus geometry từ search/binding panel
4.2. Form state
entityForm- dùng cho form tạo entity local
geometryMetaFormtype_keytime_starttime_endbinding
geometryMetaForm.binding hiện chủ yếu là giá trị hiển thị/đồng bộ UI, còn chỉnh sửa binding thật đi qua GeometryBindingPanel.
4.3. Project/session task state
useProjectSessionState() gom các cờ async vào một state machine nhỏ:
sectionTask: "idle" | "saving" | "submitting" | "opening-project"
Từ đó sinh ra:
isSavingisSubmittingisOpeningSection
Ngoài ra còn có:
activeSectionprojectStatesectionCommitsbaselineSnapshotcommitTitle
4.4. Timeline state
useTimelineState() giữ:
timelineYeartimelineDraftYearisTimelineLoadingtimelineStatus
Trong page hiện tại, timeline filter đang dùng timelineDraftYear.
Không có fetch dữ liệu project theo timelineYear; timeline đang là client-side visibility filter.
4.5. Background/session UI
useBackgroundSessionState() giữ:
backgroundVisibilityisBackgroundVisibilityReady
Giá trị thật được load từ localStorage key uhm.backgroundLayerVisibility.v1.
4.6. Wiki/session state
useWikiSessionState() giữ:
snapshotWikissnapshotEntityWikiLinks
Đây là single source of truth cho phần wiki trong snapshot commit.
5. Snapshot state
Editor đang làm việc với 3 snapshot collection chính ngoài geometry:
snapshotEntitiessnapshotWikissnapshotEntityWikiLinks
Chúng đại diện cho "current session snapshot", không phải danh sách delta thô.
Ví dụ:
- entity ref được giữ bằng
operation: "reference" - entity/wiki local mới tạo có thể mang
operation: "create" - link entity-wiki mới tạo dùng
operation: "binding"
Khi commit, buildEditorSnapshot() sẽ so với baselineSnapshot để chuyển các collection này thành snapshot đúng semantic cho backend.
6. Baseline snapshot là gì
baselineSnapshot là snapshot đang được xem như gốc của session hiện tại.
Nó được cập nhật khi:
- mở project
- commit thành công
- restore từ một commit
baselineSnapshot được dùng để:
- biết link nào là
reference, link nào làbinding, link nào làdelete - biết wiki/entity nào là thay đổi thực sự so với snapshot trước
- giữ lại inline entity/wiki từ snapshot trước nếu user chưa xóa chúng
7. Derived state quan trọng trong page
timelineVisibleDraft
- là
draftđã qua filter timeline nếutimelineFilterEnabled = true - geometry mới tạo trong session không bị timeline filter ẩn
snapshotEntitiesVisible
- loại bỏ các row
delete - dedupe theo
id
selectedFeatures
- map từ
selectedFeatureIdssang feature thật trongeditor.draft.features
isMultiEditValid
- chỉ
truekhi tất cả geometry đang chọn cùnggeometry.type - một số thao tác bind sẽ chặn nếu giá trị này là
false
pendingSaveCount
Được tính như sau:
editor.changeCount+1nếu wiki dirty+1nếu entities dirty+1nếu entity-wiki dirty
Đây là con số dùng trong UI commit, không phải số record backend chắc chắn sẽ thay đổi.
8. Dirty detection
Dirty check của:
snapshotWikissnapshotEntitiessnapshotEntityWikiLinks
đều đang làm bằng cách normalize trước rồi so JSON.stringify.
Điều này đủ thực dụng cho snapshot cỡ vừa, nhưng cần lưu ý:
- không tối ưu cho dữ liệu rất lớn
- phụ thuộc vào tính ổn định của thứ tự mảng sau normalize
9. State được persist vào localStorage
Hiện editor chỉ persist hai nhóm nhỏ:
- background layer visibility
- key:
uhm.backgroundLayerVisibility.v1
- key:
- map projection
- key:
uhm:mapProjection
- key:
Editor hiện không persist toàn bộ draft/project snapshot vào localStorage. Nếu cần autosave local draft, đó là tính năng phải làm thêm, không phải behavior hiện tại.
10. Khi nào state bị reset
Reset toàn phần
Xảy ra khi:
- mở project khác
- mở lại project
- restore commit
Hiệu ứng:
initialDatađổiuseEditorState()resetdraftundoStackbị clear- baseline map được build lại
Reset cục bộ
- đổi selection có thể reset
geometryMetaForm - đóng/mở wiki modal không reset snapshot wiki, chỉ reset form local của modal
11. Một số giới hạn hiện tại cần nhớ khi đọc code
- có
undo, chưa córedo - timeline state có
timelineYear, nhưng page hiện dùngtimelineDraftYearcho filtering - dirty count của commit không tương ứng một-một với số mutation backend
- map selection, binding filter và timeline filter đều là state client-side