feat(control-station): add compute contour workspace

This commit is contained in:
DCCONSTRUCTIONS
2026-07-28 00:54:49 +03:00
parent 1f4c960cc4
commit 1c0181297d
16 changed files with 987 additions and 262 deletions
+35 -37
View File
@@ -21,12 +21,15 @@ import {
Window,
WindowFooterActions,
useApplicationWorkspace,
type ApplicationPanelUtilityAction,
} from "@nodedc/ui-react";
import { LandingStage } from "./components/LandingStage";
import { EnvironmentSettingsWindow } from "./components/EnvironmentSettingsWindow";
import { ObservationSessionSelect } from "./components/ObservationSessionSelect";
import { SystemNavigationPanel } from "./components/system/SystemNavigationPanel";
import { SystemWorkspaceSelector } from "./components/system/SystemWorkspaceSelector";
import { useComputeContourSettings } from "./components/system/useComputeContourSettings";
import { useApplicationPanelActions } from "./components/useApplicationPanelActions";
import { useEnvironmentSettings } from "./core/environment/useEnvironmentSettings";
import { useDevicePluginHost } from "./core/device-plugins/DevicePluginHost";
import { useMissionRuntime } from "./core/runtime/MissionRuntimeContext";
@@ -151,6 +154,7 @@ function mergeViewerSettings(
export default function App() {
const runtime = useMissionRuntime();
const environment = useEnvironmentSettings();
const computeContourSettings = useComputeContourSettings();
const { selection } = useDevicePluginHost();
const polygonDatasetRoute = useMemo(
() => resolvePolygonRunRoute(typeof window === "undefined" ? "" : window.location.search),
@@ -439,8 +443,14 @@ export default function App() {
const selectRoot = (rootId: RootId) => {
setActiveRoot(rootId);
workspace.closeView();
workspace.openNavigation();
if (rootId === "system") {
workspace.openView(
activeDefinition?.root === "system" ? activeDefinition.id : "modules",
);
} else {
workspace.closeView();
}
};
const openView = (viewId: string) => {
@@ -604,35 +614,13 @@ export default function App() {
return () => window.clearTimeout(timer);
}, [layoutSaveNotice]);
const contentActions = useMemo<ApplicationPanelUtilityAction[]>(() => {
const actions: ApplicationPanelUtilityAction[] = [];
if (activeDefinition?.kind === "device") {
actions.push({
label: "Обновить состояние локального контура",
icon: "refresh",
onClick: () => void runtime.refresh(),
});
}
if (
activeDefinition
&& ["spatial", "recordings"].includes(activeDefinition.kind)
) {
actions.push(
{
label: workspaceLayoutProfile.state === "saving"
? "Сохраняем компоновку"
: "Сохранить компоновку",
icon: "save",
disabled: workspaceLayoutProfile.state === "saving",
onClick: () => void saveWorkspaceLayout(),
},
);
}
return actions;
}, [activeDefinition?.kind, runtime, saveWorkspaceLayout, workspaceLayoutProfile.state]);
const contentActions = useApplicationPanelActions({
definition: activeDefinition,
refreshRuntime: runtime.refresh,
saveWorkspaceLayout,
workspaceLayoutSaving: workspaceLayoutProfile.state === "saving",
systemUtilityAction: computeContourSettings.utilityAction,
});
const header = (
<AppHeader
@@ -702,7 +690,13 @@ export default function App() {
onOpenWorkspace={openView}
/>
}
navigation={currentRoot ? (
navigation={currentRoot && activeRoot === "system" ? (
<SystemNavigationPanel
title={currentRoot.title}
onAdd={computeContourSettings.openCreate}
onClose={workspace.closeNavigation}
/>
) : currentRoot ? (
<AdminNavigationPanel
eyebrow="MISSION CORE"
title={currentRoot.title}
@@ -718,7 +712,9 @@ export default function App() {
selection?.model.displayName ||
"Модель не выбрана",
icon: <Icon name="network" />,
active: runtime.backendStatus !== "offline" && runtime.backendStatus !== "unconfigured",
active:
runtime.backendStatus !== "offline"
&& runtime.backendStatus !== "unconfigured",
},
]}
items={rootWorkspaces.map((item) => ({
@@ -795,10 +791,11 @@ export default function App() {
<StatusBadge tone="neutral">Offline evaluation</StatusBadge>
) : activeDefinition.kind === "lab-archive" ? (
null
) : activeDefinition.kind === "compute-modules" ? (
<StatusBadge tone="neutral">Живая телеметрия</StatusBadge>
) : activeDefinition.kind === "network-monitor" ? (
<StatusBadge tone="neutral">Живая сеть</StatusBadge>
) : activeDefinition.root === "system" ? (
<SystemWorkspaceSelector
value={activeDefinition.id}
onChange={openView}
/>
) : (
<StatusBadge tone="warning">Интерфейс готов</StatusBadge>
)
@@ -864,6 +861,7 @@ export default function App() {
onSave={environment.save}
onUpload={environment.upload}
/>
{computeContourSettings.window}
<Window
open={sceneWorkspaceActive && sourceWindowOpen}