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:
Дмитрий Соловьев
2026-05-30 15:28:34 +03:00
parent c3a1a8b4a1
commit f084775cbb
58 changed files with 6609 additions and 7 deletions
@@ -15,6 +15,16 @@ type Tgu2DMapViewProps = {
layers: Tgu2DMapLayersState;
redrawToken: number;
onObjectSelect: (selection?: Tgu2DMapSelection) => void;
pickMode?: boolean;
onPickPoint?: (point: { lat: number; lon: number }) => void;
targets?: Tgu2DMapTarget[];
};
export type Tgu2DMapTarget = {
id: string;
name: string;
lat: number;
lon: number;
};
type DragState = {
@@ -39,7 +49,15 @@ const INITIAL_VIEW: MapViewState = {
zoom: 2
};
export function Tgu2DMapView({ scene, layers, redrawToken, onObjectSelect }: Tgu2DMapViewProps) {
export function Tgu2DMapView({
scene,
layers,
redrawToken,
onObjectSelect,
pickMode = false,
onPickPoint,
targets = []
}: Tgu2DMapViewProps) {
const wrapperRef = useRef<HTMLDivElement | null>(null);
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const dragRef = useRef<DragState | undefined>(undefined);
@@ -199,6 +217,12 @@ export function Tgu2DMapView({ scene, layers, redrawToken, onObjectSelect }: Tgu
const onClick = (event: React.MouseEvent) => {
const screenPoint = screenPointFromEvent(event);
if (pickMode) {
onPickPoint?.(projection.unproject(screenPoint));
onObjectSelect(undefined);
return;
}
const polygon = hitTestPolygons(polygonIndex, projection.unproject(screenPoint));
selectedPolygonRef.current = polygon;
@@ -239,7 +263,7 @@ export function Tgu2DMapView({ scene, layers, redrawToken, onObjectSelect }: Tgu
return (
<div
className="tgu-2d-map"
className={`tgu-2d-map ${pickMode ? "is-picking" : ""}`}
ref={wrapperRef}
onClick={onClick}
onPointerDown={onPointerDown}
@@ -265,6 +289,17 @@ export function Tgu2DMapView({ scene, layers, redrawToken, onObjectSelect }: Tgu
className={polygon.id === selectedPolygon?.id ? "is-selected" : "is-hovered"}
/>
))}
{targets.map((target) => {
const screen = projection.project(target);
return (
<g className="tgu-2d-map__target" key={target.id} transform={`translate(${screen.x} ${screen.y})`}>
<circle r="6" />
<line x1="-10" x2="10" y1="0" y2="0" />
<line x1="0" x2="0" y1="-10" y2="10" />
<text x="10" y="-8">{target.name}</text>
</g>
);
})}
</svg>
{tooltip && (
<div className="tgu-2d-map__tooltip" style={{ left: tooltip.x, top: tooltip.y }}>