feat(observatory): seal blocked run preparations
This commit is contained in:
@@ -171,7 +171,7 @@ export const workspaces: WorkspaceDefinition[] = [
|
||||
id: "observatory",
|
||||
root: "polygon",
|
||||
label: "Обсерватория",
|
||||
title: "Обсерватория восприятия",
|
||||
title: "Проверка компьютерного зрения",
|
||||
eyebrow: "ТЕСТОВЫЙ КОНТУР / ОБСЕРВАТОРИЯ",
|
||||
description: "Сессии и квалификация компьютерного зрения без доступа к управлению.",
|
||||
icon: "eye",
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
.observatory-workspace {
|
||||
display: grid;
|
||||
grid-auto-rows: max-content;
|
||||
align-content: start;
|
||||
gap: 1rem;
|
||||
min-width: 0;
|
||||
min-height: 100%;
|
||||
@@ -37,6 +39,14 @@
|
||||
margin: 0.3rem 0 0;
|
||||
}
|
||||
|
||||
.observatory-catalog-bar h3,
|
||||
.observatory-session-summary h3,
|
||||
.observatory-evidence h3 {
|
||||
font-size: var(--nodedc-font-size-lg);
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.observatory-lead p,
|
||||
.observatory-catalog-bar p,
|
||||
.observatory-state p,
|
||||
@@ -44,7 +54,14 @@
|
||||
max-width: 52rem;
|
||||
margin: 0.35rem 0 0;
|
||||
color: var(--nodedc-text-muted);
|
||||
line-height: 1.5;
|
||||
font-size: var(--nodedc-font-size-sm);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.observatory-catalog-bar,
|
||||
.observatory-session-summary {
|
||||
align-self: start;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.observatory-catalog-bar__copy {
|
||||
@@ -77,6 +94,8 @@
|
||||
|
||||
.observatory-session-stack {
|
||||
display: grid;
|
||||
grid-auto-rows: max-content;
|
||||
align-content: start;
|
||||
gap: 0.9rem;
|
||||
container-name: observatory-session;
|
||||
container-type: inline-size;
|
||||
@@ -130,6 +149,8 @@
|
||||
margin: 0;
|
||||
overflow-wrap: anywhere;
|
||||
color: var(--nodedc-text-secondary);
|
||||
font-size: var(--nodedc-font-size-sm);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.observatory-session-summary__end {
|
||||
@@ -168,7 +189,8 @@
|
||||
max-width: 68rem;
|
||||
margin: 0.3rem 0 0;
|
||||
color: var(--nodedc-text-muted);
|
||||
line-height: 1.45;
|
||||
font-size: var(--nodedc-font-size-sm);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.observatory-setup-detail__badges,
|
||||
@@ -212,6 +234,8 @@
|
||||
margin: 0;
|
||||
overflow-wrap: anywhere;
|
||||
color: var(--nodedc-text-secondary);
|
||||
font-size: var(--nodedc-font-size-sm);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.observatory-setup-results {
|
||||
@@ -250,6 +274,8 @@
|
||||
|
||||
.observatory-setup-results small {
|
||||
color: var(--nodedc-text-muted);
|
||||
font-size: var(--nodedc-font-size-sm);
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.observatory-setup-detail__footer {
|
||||
|
||||
@@ -145,6 +145,7 @@ export function ObservatoryWorkspace({
|
||||
const [mutationReconciliation, setMutationReconciliation] = useState<
|
||||
ObservatoryMutationReconciliation | null
|
||||
>(null);
|
||||
const overviewRef = useRef<HTMLElement | null>(null);
|
||||
const replayCoordinatorRef = useRef(createObservationReplayCoordinator());
|
||||
const items = controller.catalog?.items ?? EMPTY_OBSERVATORY_ITEMS;
|
||||
|
||||
@@ -153,6 +154,11 @@ export function ObservatoryWorkspace({
|
||||
setReplay((current) => current.kind === "closed" ? current : { kind: "closed" });
|
||||
}, []);
|
||||
|
||||
const returnToOverview = useCallback(() => {
|
||||
closeReplay();
|
||||
overviewRef.current?.scrollIntoView({ block: "start" });
|
||||
}, [closeReplay]);
|
||||
|
||||
useEffect(() => {
|
||||
if (items.some((item) => item.source.id === selectedSessionId)) return;
|
||||
closeReplay();
|
||||
@@ -352,7 +358,7 @@ export function ObservatoryWorkspace({
|
||||
data-observatory-authority="observation-only"
|
||||
data-observatory-viewer={replay.kind === "ready" ? "attached" : "detached"}
|
||||
>
|
||||
<section className="observatory-lead">
|
||||
<section ref={overviewRef} className="observatory-lead">
|
||||
<div>
|
||||
<span className="section-eyebrow">{definition.eyebrow}</span>
|
||||
<h2>{definition.title}</h2>
|
||||
@@ -368,7 +374,7 @@ export function ObservatoryWorkspace({
|
||||
</StatusBadge>
|
||||
</section>
|
||||
|
||||
<GlassSurface className="observatory-catalog-bar" padding="lg">
|
||||
<GlassSurface className="observatory-catalog-bar" padding="md">
|
||||
<div className="observatory-catalog-bar__copy">
|
||||
<span className="section-eyebrow">ИСТОЧНИК ДОКАЗАТЕЛЬСТВ</span>
|
||||
<h3>Сохранённая сессия</h3>
|
||||
@@ -606,7 +612,7 @@ export function ObservatoryWorkspace({
|
||||
<h3>Проверяем точную связь результата с исходной сессией</h3>
|
||||
<p>Визуализатор и данные маршрута ещё не запущены.</p>
|
||||
</div>
|
||||
<Button size="compact" variant="ghost" onClick={closeReplay}>Отменить</Button>
|
||||
<Button size="compact" variant="ghost" onClick={returnToOverview}>Отменить</Button>
|
||||
</GlassSurface>
|
||||
) : replay.kind === "error" ? (
|
||||
<GlassSurface className="observatory-replay-state" padding="lg" role="alert">
|
||||
@@ -623,7 +629,7 @@ export function ObservatoryWorkspace({
|
||||
>
|
||||
Повторить
|
||||
</Button>
|
||||
<Button size="compact" variant="ghost" onClick={closeReplay}>Закрыть</Button>
|
||||
<Button size="compact" variant="ghost" onClick={returnToOverview}>Закрыть</Button>
|
||||
</div>
|
||||
</GlassSurface>
|
||||
) : replay.kind === "ready" ? (
|
||||
@@ -638,7 +644,7 @@ export function ObservatoryWorkspace({
|
||||
size="compact"
|
||||
variant="secondary"
|
||||
icon={<Icon name="close" size={14} />}
|
||||
onClick={closeReplay}
|
||||
onClick={returnToOverview}
|
||||
>
|
||||
Закрыть разбор
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user