Таймлайн ТГУ: по умолчанию только актуальная цепочка планов
Раньше таймлайн рисовал планы всех статусов, включая историю версий (SUPERSEDED/EXPIRED/REJECTED), из-за чего активная цепочка тонула в наложении старых планов. Теперь по умолчанию показываются только актуальные планы (PLANNED/ISSUING/WAITING_DECISION/ACCEPTED), а историю версий можно включить чекбоксом над таймлайном.
This commit is contained in:
@@ -10,6 +10,7 @@ import { TguPlanningLayout } from "./TguPlanningLayout";
|
|||||||
import { TguSidebar } from "./TguSidebar";
|
import { TguSidebar } from "./TguSidebar";
|
||||||
import { TguTimeline } from "./TguTimeline";
|
import { TguTimeline } from "./TguTimeline";
|
||||||
import { TguToolbar } from "./TguToolbar";
|
import { TguToolbar } from "./TguToolbar";
|
||||||
|
import { isActivePlanStatus } from "./tguStatus";
|
||||||
import { buildPlatformsForInterval, buildTimelineRows, mapPlans } from "./tguTimelineMapper";
|
import { buildPlatformsForInterval, buildTimelineRows, mapPlans } from "./tguTimelineMapper";
|
||||||
|
|
||||||
const DAY_MS = 24 * 60 * 60 * 1000;
|
const DAY_MS = 24 * 60 * 60 * 1000;
|
||||||
@@ -28,6 +29,9 @@ export function TguPlanningPage() {
|
|||||||
const [selectedSpacecraftId, setSelectedSpacecraftId] = useState<string>();
|
const [selectedSpacecraftId, setSelectedSpacecraftId] = useState<string>();
|
||||||
const [selectedPlanId, setSelectedPlanId] = useState<string>();
|
const [selectedPlanId, setSelectedPlanId] = useState<string>();
|
||||||
const [activeTab, setActiveTab] = useState<TguActiveTab>("timeline");
|
const [activeTab, setActiveTab] = useState<TguActiveTab>("timeline");
|
||||||
|
// По умолчанию на таймлайне видна только актуальная цепочка; история версий
|
||||||
|
// (SUPERSEDED/EXPIRED/REJECTED и т.п.) скрыта, чтобы не было визуальной каши.
|
||||||
|
const [showHistory, setShowHistory] = useState(false);
|
||||||
// Вкладки рендерятся в режиме keep-alive: каждую монтируем при первом открытии
|
// Вкладки рендерятся в режиме keep-alive: каждую монтируем при первом открытии
|
||||||
// и дальше держим смонтированной (скрытой через display:none), чтобы её
|
// и дальше держим смонтированной (скрытой через display:none), чтобы её
|
||||||
// внутреннее состояние — загруженные заявки, выбор, слои, скролл — не сбрасывалось
|
// внутреннее состояние — загруженные заявки, выбор, слои, скролл — не сбрасывалось
|
||||||
@@ -98,9 +102,14 @@ export function TguPlanningPage() {
|
|||||||
() => buildPlatformsForInterval(rawPlatforms, plans, appliedRange),
|
() => buildPlatformsForInterval(rawPlatforms, plans, appliedRange),
|
||||||
[rawPlatforms, plans, appliedRange]
|
[rawPlatforms, plans, appliedRange]
|
||||||
);
|
);
|
||||||
|
// Планы, показываемые на таймлайне: по умолчанию только актуальная цепочка.
|
||||||
|
const timelinePlans = useMemo(
|
||||||
|
() => (showHistory ? plans : plans.filter((plan) => isActivePlanStatus(plan.status))),
|
||||||
|
[plans, showHistory]
|
||||||
|
);
|
||||||
const rows = useMemo(
|
const rows = useMemo(
|
||||||
() => buildTimelineRows(plans, platforms, appliedRange, selectedSpacecraftId),
|
() => buildTimelineRows(timelinePlans, platforms, appliedRange, selectedSpacecraftId),
|
||||||
[plans, platforms, appliedRange, selectedSpacecraftId]
|
[timelinePlans, platforms, appliedRange, selectedSpacecraftId]
|
||||||
);
|
);
|
||||||
const selectedPlan = useMemo(() => {
|
const selectedPlan = useMemo(() => {
|
||||||
const plan = plans.find((item) => item.planId === selectedPlanId);
|
const plan = plans.find((item) => item.planId === selectedPlanId);
|
||||||
@@ -181,6 +190,16 @@ export function TguPlanningPage() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<section className="tgu-center">
|
<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
|
<TguTimeline
|
||||||
rows={rows}
|
rows={rows}
|
||||||
range={appliedRange}
|
range={appliedRange}
|
||||||
|
|||||||
@@ -14,6 +14,19 @@ export const STATUS_STYLES: TimelineStatusStyle[] = [
|
|||||||
|
|
||||||
const STATUS_BY_NAME = new Map(STATUS_STYLES.map((style) => [style.status, style]));
|
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 {
|
export function statusStyle(status: TguPlanStatus): TimelineStatusStyle {
|
||||||
return (
|
return (
|
||||||
STATUS_BY_NAME.get(status) ?? {
|
STATUS_BY_NAME.get(status) ?? {
|
||||||
|
|||||||
@@ -346,6 +346,27 @@
|
|||||||
background: #121516;
|
background: #121516;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tgu-timeline-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 0.6rem 0.85rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tgu-timeline-controls__toggle {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: var(--muted, #9aa4ad);
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tgu-timeline-controls__toggle input {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.tgu-timeline {
|
.tgu-timeline {
|
||||||
min-width: 48rem;
|
min-width: 48rem;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
|
|||||||
Reference in New Issue
Block a user