Add PCP architecture docs and TGU ops updates

Capture current PCP architecture notes, service-map prototypes, TGU operations UI/map work, local configuration updates, database helper scripts, and request/sample JSON artifacts.
This commit is contained in:
Дмитрий Соловьев
2026-05-30 14:18:19 +03:00
parent 9fca4d4051
commit c3a1a8b4a1
86 changed files with 10426 additions and 74 deletions
@@ -0,0 +1,110 @@
import type { TguPlatformUi } from "../../model/timelineTypes";
import { filterPlatforms, platformLabel } from "../tgu-planning/tguTimelineMapper";
import { TGU_2D_MAP_LAYERS, type Tgu2DMapLayerKey, type Tgu2DMapLayersState } from "./model/mapLayerTypes";
import type { Tgu2DMapLayerAvailability } from "./Tgu2DMapLayers";
type Tgu2DMapSidebarProps = {
platforms: TguPlatformUi[];
selectedSpacecraftId?: string;
selectedPlanId?: string;
layers: Tgu2DMapLayersState;
search: string;
layerAvailability: Tgu2DMapLayerAvailability;
onSearchChange: (value: string) => void;
onSelectSpacecraft: (spacecraftId?: string) => void;
onToggleLayer: (key: Tgu2DMapLayerKey) => void;
};
export function Tgu2DMapSidebar({
platforms,
selectedSpacecraftId,
selectedPlanId,
layers,
search,
layerAvailability,
onSearchChange,
onSelectSpacecraft,
onToggleLayer
}: Tgu2DMapSidebarProps) {
const filteredPlatforms = filterPlatforms(platforms, search);
return (
<aside className="tgu-map-panel">
<div className="tgu-panel-heading">
<span>Карта 2D</span>
<button className="tgu-link-button" type="button" onClick={() => onSelectSpacecraft(undefined)}>
Все
</button>
</div>
<div className="tgu-map-panel__section">
<div className="tgu-map-panel__label">Выбранный план</div>
<div className="tgu-map-panel__value mono">{selectedPlanId || "-"}</div>
</div>
<div className="tgu-map-panel__section">
<div className="tgu-map-panel__label">Слои</div>
<div className="tgu-map-layer-list">
{TGU_2D_MAP_LAYERS.map((layer) => (
<label className="tgu-map-layer" key={layer.key}>
<input type="checkbox" checked={layers[layer.key]} onChange={() => onToggleLayer(layer.key)} />
<span>
<span className="tgu-map-layer__title">{layer.label}</span>
<span className="tgu-map-layer__description">{layer.description}</span>
{layers[layer.key] && layerAvailability[layer.key] && (
<span className="tgu-map-layer__warning">{layerAvailability[layer.key]}</span>
)}
</span>
</label>
))}
</div>
</div>
<div className="tgu-map-panel__section">
<div className="tgu-map-panel__label">Космические аппараты</div>
<div className="tgu-search">
<input
type="search"
placeholder="Поиск name / NORAD / mission"
value={search}
onChange={(event) => onSearchChange(event.target.value)}
/>
</div>
<div className="tgu-map-spacecraft-list">
{filteredPlatforms.map((platform) => {
const selected = selectedSpacecraftId === platform.spacecraftId;
return (
<button
className={`tgu-map-spacecraft ${selected ? "is-selected" : ""}`}
type="button"
key={platform.spacecraftId}
onClick={() => onSelectSpacecraft(platform.spacecraftId)}
>
<span>
<span className="tgu-map-spacecraft__name">{platformLabel(platform, platform.spacecraftId)}</span>
<span className="tgu-map-spacecraft__meta">
NORAD {platform.noradId || platform.spacecraftId}
{platform.mission ? ` · ${platform.mission}` : ""}
</span>
</span>
<span className="tgu-spacecraft__count">{platform.planCount}</span>
</button>
);
})}
{filteredPlatforms.length === 0 && <div className="tgu-empty tgu-empty--compact">Нет КА по текущему поиску.</div>}
</div>
</div>
<div className="tgu-map-panel__section">
<div className="tgu-map-panel__label">Статусы планов</div>
<div className="tgu-map-status-legend">
<span><i className="status-accepted" />ACCEPTED</span>
<span><i className="status-rejected" />REJECTED</span>
<span><i className="status-waiting" />WAITING_DECISION</span>
<span><i className="status-planned" />PLANNED</span>
<span><i className="status-issuing" />ISSUING</span>
<span><i className="status-expired" />EXPIRED</span>
<span><i className="status-superseded" />SUPERSEDED</span>
<span><i className="status-ambiguous" />START_AMBIGUOUS</span>
</div>
</div>
</aside>
);
}