pcp-tgu-ops-ui: убрать SUPERSEDED/EXPIRED и чекбокс истории на вкладке «Планы»

Статусы SUPERSEDED/EXPIRED удалены из модели tgu-service, поэтому чистим их и
во фронте, чтобы не описывать несуществующие состояния.

- tguTypes: убраны EXPIRED/SUPERSEDED из union TguPlanStatus.
- tguStatus: удалены их стили; заодно снят осиротевший фильтр
  isActivePlanStatus/ACTIVE_PLAN_STATUSES (после удаления чекбокса не нужен).
- tguTimelineMapper: EXPIRED убран из PROBLEM_STATUSES.
- tgu-planning.css: удалены классы .status-superseded/.status-expired и
  осиротевший блок .tgu-timeline-controls.
- TguPlanningPage: убран тумблер «Показать историю версий» вместе со стейтом
  showHistory и фильтром timelinePlans — таймлайн рендерит все планы из API
  напрямую (перестали скрываться AWAITING_LAYIN/REJECTED/LAYIN_FAILED/NOT_ACCEPTED).

EXPIRED в requestTypes (статус заявок) — отдельный домен, не тронут.
This commit is contained in:
Дмитрий Соловьев
2026-06-02 14:33:04 +03:00
parent c76a823dbc
commit 86215b300a
5 changed files with 3 additions and 68 deletions
@@ -10,7 +10,6 @@ import { TguPlanningLayout } from "./TguPlanningLayout";
import { TguSidebar } from "./TguSidebar";
import { TguTimeline } from "./TguTimeline";
import { TguToolbar } from "./TguToolbar";
import { isActivePlanStatus } from "./tguStatus";
import { buildPlatformsForInterval, buildTimelineRows, mapPlans } from "./tguTimelineMapper";
const DAY_MS = 24 * 60 * 60 * 1000;
@@ -29,9 +28,6 @@ export function TguPlanningPage() {
const [selectedSpacecraftId, setSelectedSpacecraftId] = useState<string>();
const [selectedPlanId, setSelectedPlanId] = useState<string>();
const [activeTab, setActiveTab] = useState<TguActiveTab>("timeline");
// По умолчанию на таймлайне видна только актуальная цепочка; история версий
// (SUPERSEDED/EXPIRED/REJECTED и т.п.) скрыта, чтобы не было визуальной каши.
const [showHistory, setShowHistory] = useState(false);
// Вкладки рендерятся в режиме keep-alive: каждую монтируем при первом открытии
// и дальше держим смонтированной (скрытой через display:none), чтобы её
// внутреннее состояние — загруженные заявки, выбор, слои, скролл — не сбрасывалось
@@ -102,14 +98,9 @@ export function TguPlanningPage() {
() => buildPlatformsForInterval(rawPlatforms, plans, appliedRange),
[rawPlatforms, plans, appliedRange]
);
// Планы, показываемые на таймлайне: по умолчанию только актуальная цепочка.
const timelinePlans = useMemo(
() => (showHistory ? plans : plans.filter((plan) => isActivePlanStatus(plan.status))),
[plans, showHistory]
);
const rows = useMemo(
() => buildTimelineRows(timelinePlans, platforms, appliedRange, selectedSpacecraftId),
[timelinePlans, platforms, appliedRange, selectedSpacecraftId]
() => buildTimelineRows(plans, platforms, appliedRange, selectedSpacecraftId),
[plans, platforms, appliedRange, selectedSpacecraftId]
);
const selectedPlan = useMemo(() => {
const plan = plans.find((item) => item.planId === selectedPlanId);
@@ -190,16 +181,6 @@ export function TguPlanningPage() {
}}
/>
<section className="tgu-center">
<div className="tgu-timeline-controls">
<label className="tgu-timeline-controls__toggle">
<input
type="checkbox"
checked={showHistory}
onChange={(event) => setShowHistory(event.target.checked)}
/>
Показать историю версий (SUPERSEDED, EXPIRED и др.)
</label>
</div>
<TguTimeline
rows={rows}
range={appliedRange}
@@ -7,26 +7,11 @@ export const STATUS_STYLES: TimelineStatusStyle[] = [
{ status: "WAITING_DECISION", label: "WAITING_DECISION", color: "#f0ad2e", className: "status-waiting" },
{ status: "PLANNED", label: "PLANNED", color: "#8d99a6", className: "status-planned" },
{ status: "ISSUING", label: "ISSUING", color: "#2f80ed", className: "status-issuing" },
{ status: "EXPIRED", label: "EXPIRED", color: "#495057", className: "status-expired" },
{ status: "SUPERSEDED", label: "SUPERSEDED", color: "#c7ced6", className: "status-superseded" },
{ status: "START_AMBIGUOUS", label: "START_AMBIGUOUS", color: "#b42318", className: "status-ambiguous" }
];
const STATUS_BY_NAME = new Map(STATUS_STYLES.map((style) => [style.status, style]));
/** Статусы актуальной цепочки: их показываем на таймлайне по умолчанию. */
const ACTIVE_PLAN_STATUSES = new Set<TguPlanStatus>([
"PLANNED",
"ISSUING",
"WAITING_DECISION",
"ACCEPTED"
]);
/** Проверяет, относится ли план к актуальной цепочке (а не к истории версий). */
export function isActivePlanStatus(status: TguPlanStatus): boolean {
return ACTIVE_PLAN_STATUSES.has(status);
}
export function statusStyle(status: TguPlanStatus): TimelineStatusStyle {
return (
STATUS_BY_NAME.get(status) ?? {
@@ -1,7 +1,7 @@
import type { TguPlan, TguPlatform } from "../../model/tguTypes";
import type { TguPlanUi, TguPlatformUi, TimelineRange, TimelineRow } from "../../model/timelineTypes";
const PROBLEM_STATUSES = new Set(["REJECTED", "EXPIRED", "START_AMBIGUOUS"]);
const PROBLEM_STATUSES = new Set(["REJECTED", "START_AMBIGUOUS"]);
export function mapPlans(plans: TguPlan[], platforms: TguPlatform[]): TguPlanUi[] {
const platformByNorad = buildPlatformByNorad(platforms);