feat(tgu-ops-ui): add spacecraft work editor tab
Port the TGU editor prototype into pcp-tgu-ops-ui as a new editor tab, add draft/conflict/pass logic with tests, extend the 2D map picking API, and include editor styles/theme aliases and task/prototype docs. Validation: npm run test; npm run build in services/pcp-tgu-ops-ui.
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import type { TguPlanUi, TguPlatformUi } from "../../model/timelineTypes";
|
||||
import { formatDuration } from "./editorPresentation";
|
||||
|
||||
type EditorToolbarProps = {
|
||||
selectedSpacecraftId?: string;
|
||||
selectedPlan?: TguPlanUi;
|
||||
platforms: TguPlatformUi[];
|
||||
canUndo: boolean;
|
||||
canRedo: boolean;
|
||||
checking: boolean;
|
||||
conflictCount: number;
|
||||
addedCount: number;
|
||||
dirty: boolean;
|
||||
applying: boolean;
|
||||
windowLabel: string;
|
||||
rightMode: "none" | "inspect" | "shoot" | "downlink";
|
||||
onSetRightMode: (mode: "shoot" | "downlink") => void;
|
||||
onUndo: () => void;
|
||||
onRedo: () => void;
|
||||
onCheck: () => void;
|
||||
onApply: () => void;
|
||||
onZoom: (factor: number) => void;
|
||||
onPan: (factor: number) => void;
|
||||
};
|
||||
|
||||
export function EditorToolbar({
|
||||
selectedSpacecraftId,
|
||||
selectedPlan,
|
||||
platforms,
|
||||
canUndo,
|
||||
canRedo,
|
||||
checking,
|
||||
conflictCount,
|
||||
addedCount,
|
||||
dirty,
|
||||
applying,
|
||||
windowLabel,
|
||||
rightMode,
|
||||
onSetRightMode,
|
||||
onUndo,
|
||||
onRedo,
|
||||
onCheck,
|
||||
onApply,
|
||||
onZoom,
|
||||
onPan
|
||||
}: EditorToolbarProps) {
|
||||
const platformLabel = selectedSpacecraftId
|
||||
? platforms.find((platform) => platform.spacecraftId === selectedSpacecraftId)?.name ?? selectedSpacecraftId
|
||||
: "КА не выбран";
|
||||
|
||||
return (
|
||||
<div className="tgu-editor-toolbar">
|
||||
<div className="tgu-editor-toolbar__identity">
|
||||
<span className="tgu-editor-type-dot" aria-hidden="true" />
|
||||
<div>
|
||||
<div className="tgu-editor-toolbar__title">{platformLabel}</div>
|
||||
<div className="tgu-editor-toolbar__meta">
|
||||
{selectedPlan ? `${selectedPlan.planId} · ${selectedPlan.status}` : "Выберите план на timeline"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="tgu-editor-toolbar__group">
|
||||
<button
|
||||
className={`tgu-button ${rightMode === "shoot" ? "tgu-button--primary" : ""}`}
|
||||
type="button"
|
||||
onClick={() => onSetRightMode("shoot")}
|
||||
disabled={!selectedSpacecraftId}
|
||||
>
|
||||
+ Съёмка
|
||||
</button>
|
||||
<button
|
||||
className={`tgu-button ${rightMode === "downlink" ? "tgu-button--primary" : ""}`}
|
||||
type="button"
|
||||
onClick={() => onSetRightMode("downlink")}
|
||||
disabled={!selectedSpacecraftId}
|
||||
>
|
||||
+ Сброс
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="tgu-editor-toolbar__spacer" />
|
||||
|
||||
<div className="tgu-editor-window-control" aria-label="Окно редактора">
|
||||
<button type="button" onClick={() => onPan(-0.25)} title="Назад по времени">◀</button>
|
||||
<button type="button" onClick={() => onZoom(1.4)} title="Отдалить">−</button>
|
||||
<span>{windowLabel || formatDuration(0)}</span>
|
||||
<button type="button" onClick={() => onZoom(0.7)} title="Приблизить">+</button>
|
||||
<button type="button" onClick={() => onPan(0.25)} title="Вперёд по времени">▶</button>
|
||||
</div>
|
||||
|
||||
<div className="tgu-editor-toolbar__group">
|
||||
<button className="tgu-icon-button" type="button" onClick={onUndo} disabled={!canUndo} title="Отменить">
|
||||
↶
|
||||
</button>
|
||||
<button className="tgu-icon-button" type="button" onClick={onRedo} disabled={!canRedo} title="Вернуть">
|
||||
↷
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
className={`tgu-button ${conflictCount > 0 ? "tgu-editor-button--warning" : ""}`}
|
||||
type="button"
|
||||
onClick={onCheck}
|
||||
disabled={checking || !selectedSpacecraftId}
|
||||
>
|
||||
{checking ? "Проверка..." : conflictCount > 0 ? `Конфликты · ${conflictCount}` : "Проверить"}
|
||||
</button>
|
||||
|
||||
<button className="tgu-button tgu-button--primary" type="button" onClick={onApply} disabled={!dirty || applying}>
|
||||
{applying ? "Применение..." : `Применить${addedCount > 0 ? ` · +${addedCount}` : ""}`}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user