refactor: simplify timeline stage creation form by removing redundant validation logic and improving layout
Build and Release / release (push) Successful in 36s
Build and Release / release (push) Successful in 36s
This commit is contained in:
@@ -1801,6 +1801,7 @@ function EditorPageContent() {
|
|||||||
type: "Feature",
|
type: "Feature",
|
||||||
properties: {
|
properties: {
|
||||||
id: geoId,
|
id: geoId,
|
||||||
|
source: "ref",
|
||||||
type: typeKey,
|
type: typeKey,
|
||||||
time_start: normalizeTimelineYearValue(geo.time_start),
|
time_start: normalizeTimelineYearValue(geo.time_start),
|
||||||
time_end: normalizeTimelineYearValue(geo.time_end),
|
time_end: normalizeTimelineYearValue(geo.time_end),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import type {
|
import type {
|
||||||
BattleReplay,
|
BattleReplay,
|
||||||
GeoFunctionName,
|
GeoFunctionName,
|
||||||
@@ -43,46 +43,6 @@ type AnyStepAction =
|
|||||||
| ReplayAction<GeoFunctionName>
|
| ReplayAction<GeoFunctionName>
|
||||||
| ReplayAction<NarrativeFunctionName>;
|
| ReplayAction<NarrativeFunctionName>;
|
||||||
|
|
||||||
function validateReplayTimeFormat(value: string): boolean {
|
|
||||||
const trimmed = value.trim();
|
|
||||||
if (!trimmed) return false;
|
|
||||||
|
|
||||||
// 1. Check DD/MM/YYYY
|
|
||||||
const dmyRegex = /^(\d{2})\/(\d{2})\/(-?\d{4})$/;
|
|
||||||
const dmyMatch = trimmed.match(dmyRegex);
|
|
||||||
if (dmyMatch) {
|
|
||||||
const day = parseInt(dmyMatch[1], 10);
|
|
||||||
const month = parseInt(dmyMatch[2], 10);
|
|
||||||
const year = parseInt(dmyMatch[3], 10);
|
|
||||||
if (month < 1 || month > 12) return false;
|
|
||||||
if (day < 1 || day > 31) return false;
|
|
||||||
if (month === 2) {
|
|
||||||
const isLeap = (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
|
|
||||||
if (day > (isLeap ? 29 : 28)) return false;
|
|
||||||
} else if ([4, 6, 9, 11].includes(month)) {
|
|
||||||
if (day > 30) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Check MM/YYYY
|
|
||||||
const myRegex = /^(\d{2})\/(-?\d{4})$/;
|
|
||||||
const myMatch = trimmed.match(myRegex);
|
|
||||||
if (myMatch) {
|
|
||||||
const month = parseInt(myMatch[1], 10);
|
|
||||||
if (month < 1 || month > 12) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Check YYYY
|
|
||||||
const yRegex = /^(-?\d{4})$/;
|
|
||||||
if (yRegex.test(trimmed)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
type StageFormState = {
|
type StageFormState = {
|
||||||
title: string;
|
title: string;
|
||||||
detail_time_start: string;
|
detail_time_start: string;
|
||||||
@@ -143,13 +103,6 @@ export default function ReplayTimelineSidebar({
|
|||||||
detail_time_stop: "",
|
detail_time_stop: "",
|
||||||
});
|
});
|
||||||
const [createStagePanelKey, setCreateStagePanelKey] = useState(0);
|
const [createStagePanelKey, setCreateStagePanelKey] = useState(0);
|
||||||
|
|
||||||
const isStartValid = validateReplayTimeFormat(createStageForm.detail_time_start);
|
|
||||||
const isStopValid = validateReplayTimeFormat(createStageForm.detail_time_stop);
|
|
||||||
const isCreateFormValid = createStageForm.title.trim() !== "" && isStartValid && isStopValid;
|
|
||||||
|
|
||||||
const showStartError = createStageForm.detail_time_start.length > 0 && !isStartValid;
|
|
||||||
const showStopError = createStageForm.detail_time_stop.length > 0 && !isStopValid;
|
|
||||||
const [openWeightEditorKey, setOpenWeightEditorKey] = useState<string | null>(null);
|
const [openWeightEditorKey, setOpenWeightEditorKey] = useState<string | null>(null);
|
||||||
const [openActionDetailKey, setOpenActionDetailKey] = useState<string | null>(null);
|
const [openActionDetailKey, setOpenActionDetailKey] = useState<string | null>(null);
|
||||||
|
|
||||||
@@ -401,26 +354,7 @@ export default function ReplayTimelineSidebar({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDuplicateAction = (
|
|
||||||
stageId: number,
|
|
||||||
stepIndex: number,
|
|
||||||
groupKey: ActionGroupKey,
|
|
||||||
actionIndex: number,
|
|
||||||
actionTitle: string
|
|
||||||
) => {
|
|
||||||
onMutateReplay(
|
|
||||||
`Replay: nhân bản ${actionTitle} ở step ${stepIndex + 1} của stage #${stageId}`,
|
|
||||||
(draftReplay) => {
|
|
||||||
const stage = draftReplay.detail.find((item) => item.id === stageId);
|
|
||||||
if (!stage || stepIndex < 0 || stepIndex >= stage.steps.length) return;
|
|
||||||
const step = stage.steps[stepIndex];
|
|
||||||
const actions = [...getStepActionGroup(step, groupKey)];
|
|
||||||
if (actionIndex < 0 || actionIndex >= actions.length) return;
|
|
||||||
actions.splice(actionIndex + 1, 0, cloneReplayAction(actions[actionIndex]) as AnyStepAction);
|
|
||||||
setStepActionGroup(step, groupKey, actions);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleUpdateActionParams = (
|
const handleUpdateActionParams = (
|
||||||
stageId: number,
|
stageId: number,
|
||||||
@@ -603,10 +537,9 @@ export default function ReplayTimelineSidebar({
|
|||||||
onChange={(event) =>
|
onChange={(event) =>
|
||||||
setCreateStageForm((prev) => ({ ...prev, title: event.target.value }))
|
setCreateStageForm((prev) => ({ ...prev, title: event.target.value }))
|
||||||
}
|
}
|
||||||
placeholder="Title (bắt buộc)"
|
placeholder="Title"
|
||||||
style={inputStyle}
|
style={inputStyle}
|
||||||
/>
|
/>
|
||||||
<div>
|
|
||||||
<input
|
<input
|
||||||
value={createStageForm.detail_time_start}
|
value={createStageForm.detail_time_start}
|
||||||
onChange={(event) =>
|
onChange={(event) =>
|
||||||
@@ -615,19 +548,14 @@ export default function ReplayTimelineSidebar({
|
|||||||
detail_time_start: event.target.value,
|
detail_time_start: event.target.value,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
placeholder="Thời gian bắt đầu (detail_time_start)"
|
placeholder="detail_time_start (DD/MM/YYYY hoặc MM/YYYY hoặc YYYY)"
|
||||||
style={{
|
style={{
|
||||||
...inputStyle,
|
...inputStyle,
|
||||||
borderColor: showStartError ? "#ef4444" : "#334155",
|
border: createStageForm.detail_time_start && !validateReplayTimeFormat(createStageForm.detail_time_start)
|
||||||
|
? "1px solid #ef4444"
|
||||||
|
: undefined,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{showStartError ? (
|
|
||||||
<div style={{ color: "#ef4444", fontSize: 10, marginTop: 3 }}>
|
|
||||||
Định dạng không hợp lệ (DD/MM/YYYY, MM/YYYY, hoặc YYYY)
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input
|
<input
|
||||||
value={createStageForm.detail_time_stop}
|
value={createStageForm.detail_time_stop}
|
||||||
onChange={(event) =>
|
onChange={(event) =>
|
||||||
@@ -636,30 +564,39 @@ export default function ReplayTimelineSidebar({
|
|||||||
detail_time_stop: event.target.value,
|
detail_time_stop: event.target.value,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
placeholder="Thời gian kết thúc (detail_time_stop)"
|
placeholder="detail_time_stop (DD/MM/YYYY hoặc MM/YYYY hoặc YYYY)"
|
||||||
style={{
|
style={{
|
||||||
...inputStyle,
|
...inputStyle,
|
||||||
borderColor: showStopError ? "#ef4444" : "#334155",
|
border: createStageForm.detail_time_stop && !validateReplayTimeFormat(createStageForm.detail_time_stop)
|
||||||
|
? "1px solid #ef4444"
|
||||||
|
: undefined,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{showStopError ? (
|
<div style={{ fontSize: 10, color: "#94a3b8", lineHeight: 1.3 }}>
|
||||||
<div style={{ color: "#ef4444", fontSize: 10, marginTop: 3 }}>
|
* Định dạng bắt buộc: <strong>ngày/tháng/năm</strong> (00/00/0000), <strong>tháng/năm</strong> (00/0000) hoặc <strong>năm</strong> (0000).
|
||||||
Định dạng không hợp lệ (DD/MM/YYYY, MM/YYYY, hoặc YYYY)
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<div style={{ fontSize: 10, color: "#94a3b8", lineHeight: "1.4" }}>
|
|
||||||
Cấu trúc bắt buộc: <strong>DD/MM/YYYY</strong>, <strong>MM/YYYY</strong>, hoặc <strong>YYYY</strong>.
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
disabled={!isCreateFormValid}
|
|
||||||
onClick={handleCreateStage}
|
onClick={handleCreateStage}
|
||||||
|
disabled={
|
||||||
|
!createStageForm.title.trim() ||
|
||||||
|
!validateReplayTimeFormat(createStageForm.detail_time_start) ||
|
||||||
|
!validateReplayTimeFormat(createStageForm.detail_time_stop)
|
||||||
|
}
|
||||||
style={{
|
style={{
|
||||||
...buttonStyle,
|
...buttonStyle,
|
||||||
background: isCreateFormValid ? "#1d4ed8" : "#1e293b",
|
background:
|
||||||
color: isCreateFormValid ? "white" : "#64748b",
|
createStageForm.title.trim() &&
|
||||||
cursor: isCreateFormValid ? "pointer" : "not-allowed",
|
validateReplayTimeFormat(createStageForm.detail_time_start) &&
|
||||||
|
validateReplayTimeFormat(createStageForm.detail_time_stop)
|
||||||
|
? "#1d4ed8"
|
||||||
|
: "#475569",
|
||||||
|
cursor:
|
||||||
|
createStageForm.title.trim() &&
|
||||||
|
validateReplayTimeFormat(createStageForm.detail_time_start) &&
|
||||||
|
validateReplayTimeFormat(createStageForm.detail_time_stop)
|
||||||
|
? "pointer"
|
||||||
|
: "not-allowed",
|
||||||
border: "none",
|
border: "none",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -928,22 +865,7 @@ export default function ReplayTimelineSidebar({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<div style={{ display: "grid", gridTemplateColumns: "repeat(2, auto)", gap: 4 }}>
|
<div style={{ display: "grid", gridTemplateColumns: "auto", gap: 4 }}>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() =>
|
|
||||||
handleDuplicateAction(
|
|
||||||
stage.id,
|
|
||||||
stepIndex,
|
|
||||||
entry.groupKey,
|
|
||||||
entry.actionIndex,
|
|
||||||
entry.title
|
|
||||||
)
|
|
||||||
}
|
|
||||||
style={actionButtonStyle(false, "#0f766e")}
|
|
||||||
>
|
|
||||||
Copy
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -1120,23 +1042,13 @@ function StageMetadataEditor({
|
|||||||
detail_time_stop: stage.detail_time_stop || "",
|
detail_time_stop: stage.detail_time_stop || "",
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setForm({
|
|
||||||
title: stage.title || "",
|
|
||||||
detail_time_start: stage.detail_time_start || "",
|
|
||||||
detail_time_stop: stage.detail_time_stop || "",
|
|
||||||
});
|
|
||||||
}, [stage]);
|
|
||||||
|
|
||||||
const isStartValid = validateReplayTimeFormat(form.detail_time_start);
|
const isStartValid = validateReplayTimeFormat(form.detail_time_start);
|
||||||
const isStopValid = validateReplayTimeFormat(form.detail_time_stop);
|
const isStopValid = validateReplayTimeFormat(form.detail_time_stop);
|
||||||
const isEditFormValid = form.title.trim() !== "" && isStartValid && isStopValid;
|
const isTitleValid = form.title.trim().length > 0;
|
||||||
|
const isFormValid = isStartValid && isStopValid && isTitleValid;
|
||||||
const showStartError = form.detail_time_start.length > 0 && !isStartValid;
|
|
||||||
const showStopError = form.detail_time_stop.length > 0 && !isStopValid;
|
|
||||||
|
|
||||||
const handleApplyStageMetadata = () => {
|
const handleApplyStageMetadata = () => {
|
||||||
if (!isEditFormValid) return;
|
if (!isFormValid) return;
|
||||||
onMutateReplay(`Replay: cập nhật stage #${stage.id}`, (draftReplay) => {
|
onMutateReplay(`Replay: cập nhật stage #${stage.id}`, (draftReplay) => {
|
||||||
const targetStage = draftReplay.detail.find((item) => item.id === stage.id);
|
const targetStage = draftReplay.detail.find((item) => item.id === stage.id);
|
||||||
if (!targetStage) return;
|
if (!targetStage) return;
|
||||||
@@ -1154,10 +1066,9 @@ function StageMetadataEditor({
|
|||||||
onChange={(event) =>
|
onChange={(event) =>
|
||||||
setForm((prev) => ({ ...prev, title: event.target.value }))
|
setForm((prev) => ({ ...prev, title: event.target.value }))
|
||||||
}
|
}
|
||||||
placeholder="Title (bắt buộc)"
|
placeholder="Title"
|
||||||
style={inputStyle}
|
style={inputStyle}
|
||||||
/>
|
/>
|
||||||
<div>
|
|
||||||
<input
|
<input
|
||||||
value={form.detail_time_start}
|
value={form.detail_time_start}
|
||||||
onChange={(event) =>
|
onChange={(event) =>
|
||||||
@@ -1166,19 +1077,12 @@ function StageMetadataEditor({
|
|||||||
detail_time_start: event.target.value,
|
detail_time_start: event.target.value,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
placeholder="Thời gian bắt đầu (detail_time_start)"
|
placeholder="detail_time_start (DD/MM/YYYY hoặc MM/YYYY hoặc YYYY)"
|
||||||
style={{
|
style={{
|
||||||
...inputStyle,
|
...inputStyle,
|
||||||
borderColor: showStartError ? "#ef4444" : "#334155",
|
border: form.detail_time_start && !isStartValid ? "1px solid #ef4444" : undefined,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{showStartError ? (
|
|
||||||
<div style={{ color: "#ef4444", fontSize: 10, marginTop: 3 }}>
|
|
||||||
Định dạng không hợp lệ (DD/MM/YYYY, MM/YYYY, hoặc YYYY)
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<input
|
<input
|
||||||
value={form.detail_time_stop}
|
value={form.detail_time_stop}
|
||||||
onChange={(event) =>
|
onChange={(event) =>
|
||||||
@@ -1187,30 +1091,23 @@ function StageMetadataEditor({
|
|||||||
detail_time_stop: event.target.value,
|
detail_time_stop: event.target.value,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
placeholder="Thời gian kết thúc (detail_time_stop)"
|
placeholder="detail_time_stop (DD/MM/YYYY hoặc MM/YYYY hoặc YYYY)"
|
||||||
style={{
|
style={{
|
||||||
...inputStyle,
|
...inputStyle,
|
||||||
borderColor: showStopError ? "#ef4444" : "#334155",
|
border: form.detail_time_stop && !isStopValid ? "1px solid #ef4444" : undefined,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{showStopError ? (
|
<div style={{ fontSize: 10, color: "#94a3b8", lineHeight: 1.3 }}>
|
||||||
<div style={{ color: "#ef4444", fontSize: 10, marginTop: 3 }}>
|
* Định dạng bắt buộc: <strong>ngày/tháng/năm</strong> (00/00/0000), <strong>tháng/năm</strong> (00/0000) hoặc <strong>năm</strong> (0000).
|
||||||
Định dạng không hợp lệ (DD/MM/YYYY, MM/YYYY, hoặc YYYY)
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<div style={{ fontSize: 10, color: "#94a3b8", lineHeight: "1.4" }}>
|
|
||||||
Cấu trúc bắt buộc: <strong>DD/MM/YYYY</strong>, <strong>MM/YYYY</strong>, hoặc <strong>YYYY</strong>.
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
disabled={!isEditFormValid}
|
|
||||||
onClick={handleApplyStageMetadata}
|
onClick={handleApplyStageMetadata}
|
||||||
|
disabled={!isFormValid}
|
||||||
style={{
|
style={{
|
||||||
...buttonStyle,
|
...buttonStyle,
|
||||||
background: isEditFormValid ? "#0f766e" : "#1e293b",
|
background: isFormValid ? "#0f766e" : "#475569",
|
||||||
color: isEditFormValid ? "white" : "#64748b",
|
cursor: isFormValid ? "pointer" : "not-allowed",
|
||||||
cursor: isEditFormValid ? "pointer" : "not-allowed",
|
|
||||||
border: "none",
|
border: "none",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -1788,3 +1685,34 @@ function truncateText(value: string, maxLength: number) {
|
|||||||
? `${value.slice(0, Math.max(0, maxLength - 1))}…`
|
? `${value.slice(0, Math.max(0, maxLength - 1))}…`
|
||||||
: value;
|
: value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function validateReplayTimeFormat(value: string): boolean {
|
||||||
|
const val = value.trim();
|
||||||
|
if (!val) return false;
|
||||||
|
|
||||||
|
// YYYY (e.g. 1945)
|
||||||
|
if (/^\d{4}$/.test(val)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MM/YYYY (e.g. 05/1945)
|
||||||
|
if (/^(0[1-9]|1[0-2])\/\d{4}$/.test(val)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DD/MM/YYYY (e.g. 15/05/1945)
|
||||||
|
if (/^(0[1-9]|[12]\d|3[01])\/(0[1-9]|1[0-2])\/\d{4}$/.test(val)) {
|
||||||
|
const parts = val.split("/");
|
||||||
|
const d = parseInt(parts[0], 10);
|
||||||
|
const m = parseInt(parts[1], 10);
|
||||||
|
const y = parseInt(parts[2], 10);
|
||||||
|
|
||||||
|
const monthLengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
||||||
|
if ((y % 4 === 0 && y % 100 !== 0) || y % 400 === 0) {
|
||||||
|
monthLengths[1] = 29;
|
||||||
|
}
|
||||||
|
return d <= monthLengths[m - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export type FeatureId = string | number;
|
|||||||
|
|
||||||
export type FeatureProperties = {
|
export type FeatureProperties = {
|
||||||
id: FeatureId;
|
id: FeatureId;
|
||||||
|
source?: SnapshotSource;
|
||||||
type?: string | null;
|
type?: string | null;
|
||||||
geometry_preset?: GeometryPreset | null;
|
geometry_preset?: GeometryPreset | null;
|
||||||
time_start?: number | null;
|
time_start?: number | null;
|
||||||
|
|||||||
@@ -395,6 +395,7 @@ export function normalizeEditorSnapshot(raw: unknown): EditorSnapshot | null {
|
|||||||
|
|
||||||
// Generate geometry metadata onto feature properties (optional in persisted snapshot).
|
// Generate geometry metadata onto feature properties (optional in persisted snapshot).
|
||||||
const geo = geometryById.get(gid) || null;
|
const geo = geometryById.get(gid) || null;
|
||||||
|
const existingSource = p.source === "inline" || p.source === "ref" ? p.source : undefined;
|
||||||
if (geo) {
|
if (geo) {
|
||||||
const geoRecord = geo as unknown as UnknownRecord;
|
const geoRecord = geo as unknown as UnknownRecord;
|
||||||
// type can arrive as numeric geo_type, numeric string, or semantic key depending on backend version.
|
// type can arrive as numeric geo_type, numeric string, or semantic key depending on backend version.
|
||||||
@@ -406,6 +407,7 @@ export function normalizeEditorSnapshot(raw: unknown): EditorSnapshot | null {
|
|||||||
if (geo.bound_with !== undefined) {
|
if (geo.bound_with !== undefined) {
|
||||||
p.bound_with = geo.bound_with;
|
p.bound_with = geo.bound_with;
|
||||||
}
|
}
|
||||||
|
p.source = geo.source || existingSource || "inline";
|
||||||
const timeStart = normalizeTimelineYearValue(geo.time_start);
|
const timeStart = normalizeTimelineYearValue(geo.time_start);
|
||||||
const timeEnd = normalizeTimelineYearValue(geo.time_end);
|
const timeEnd = normalizeTimelineYearValue(geo.time_end);
|
||||||
if (timeStart !== null) {
|
if (timeStart !== null) {
|
||||||
@@ -418,10 +420,13 @@ export function normalizeEditorSnapshot(raw: unknown): EditorSnapshot | null {
|
|||||||
} else {
|
} else {
|
||||||
delete p.time_end;
|
delete p.time_end;
|
||||||
}
|
}
|
||||||
} else if (!existingTypeKey) {
|
} else {
|
||||||
|
p.source = existingSource || "inline";
|
||||||
|
if (!existingTypeKey) {
|
||||||
p.type = fallbackTypeKey;
|
p.type = fallbackTypeKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return cloned;
|
return cloned;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
@@ -570,7 +575,7 @@ export function buildEditorSnapshot(options: {
|
|||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
operation,
|
operation,
|
||||||
source: "inline",
|
source: feature.properties.source || "inline",
|
||||||
type: typeKey,
|
type: typeKey,
|
||||||
draw_geometry: feature.geometry,
|
draw_geometry: feature.geometry,
|
||||||
bound_with: normalizeFeatureBoundWith(feature),
|
bound_with: normalizeFeatureBoundWith(feature),
|
||||||
@@ -644,6 +649,7 @@ export function buildEditorSnapshot(options: {
|
|||||||
delete p.time_end;
|
delete p.time_end;
|
||||||
delete p.bound_with;
|
delete p.bound_with;
|
||||||
delete p.binding;
|
delete p.binding;
|
||||||
|
delete p.source;
|
||||||
delete p.entity_id;
|
delete p.entity_id;
|
||||||
delete p.entity_ids;
|
delete p.entity_ids;
|
||||||
delete p.entity_name;
|
delete p.entity_name;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export type FeatureId = string | number;
|
|||||||
|
|
||||||
export type FeatureProperties = {
|
export type FeatureProperties = {
|
||||||
id: FeatureId;
|
id: FeatureId;
|
||||||
|
source?: "inline" | "ref";
|
||||||
type?: string | null;
|
type?: string | null;
|
||||||
geometry_preset?: GeometryPreset | null;
|
geometry_preset?: GeometryPreset | null;
|
||||||
time_start?: number | null;
|
time_start?: number | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user