feat(control-station): add configurable environment shell
This commit is contained in:
@@ -8,10 +8,8 @@ import {
|
||||
Checker,
|
||||
ColorField,
|
||||
ControlRow,
|
||||
HeaderAvatar,
|
||||
HeaderNavigation,
|
||||
HeaderProfile,
|
||||
HeaderProfileButton,
|
||||
HeaderWorkspace,
|
||||
Icon,
|
||||
Inspector,
|
||||
@@ -19,6 +17,7 @@ import {
|
||||
Select,
|
||||
StatusBadge,
|
||||
TextField,
|
||||
UserProfileMenu,
|
||||
Window,
|
||||
WindowFooterActions,
|
||||
useApplicationWorkspace,
|
||||
@@ -26,7 +25,9 @@ import {
|
||||
} from "@nodedc/ui-react";
|
||||
|
||||
import { LandingStage } from "./components/LandingStage";
|
||||
import { EnvironmentSettingsWindow } from "./components/EnvironmentSettingsWindow";
|
||||
import { ObservationSessionSelect } from "./components/ObservationSessionSelect";
|
||||
import { useEnvironmentSettings } from "./core/environment/useEnvironmentSettings";
|
||||
import { useDevicePluginHost } from "./core/device-plugins/DevicePluginHost";
|
||||
import { useMissionRuntime } from "./core/runtime/MissionRuntimeContext";
|
||||
import type { ViewerSettings } from "./core/runtime/contracts";
|
||||
@@ -149,6 +150,7 @@ function mergeViewerSettings(
|
||||
|
||||
export default function App() {
|
||||
const runtime = useMissionRuntime();
|
||||
const environment = useEnvironmentSettings();
|
||||
const { selection } = useDevicePluginHost();
|
||||
const polygonDatasetRoute = useMemo(
|
||||
() => resolvePolygonRunRoute(typeof window === "undefined" ? "" : window.location.search),
|
||||
@@ -162,6 +164,7 @@ export default function App() {
|
||||
const [activeRoot, setActiveRoot] = useState<RootId | null>(
|
||||
polygonDatasetRoute.active ? "data" : null,
|
||||
);
|
||||
const [environmentSettingsOpen, setEnvironmentSettingsOpen] = useState(false);
|
||||
const [sourceUrl, setSourceUrl] = useState("");
|
||||
const [recordedReplay, setRecordedReplay] = useState<ObservationSessionReplayLaunch | null>(null);
|
||||
const [recordedReplayLabel, setRecordedReplayLabel] = useState<string | null>(null);
|
||||
@@ -423,11 +426,6 @@ export default function App() {
|
||||
|
||||
const selectRoot = (rootId: RootId) => {
|
||||
setActiveRoot(rootId);
|
||||
if (rootId === "polygon") {
|
||||
workspace.openView("lab-archive");
|
||||
workspace.openNavigation();
|
||||
return;
|
||||
}
|
||||
workspace.closeView();
|
||||
workspace.openNavigation();
|
||||
};
|
||||
@@ -626,6 +624,7 @@ export default function App() {
|
||||
const header = (
|
||||
<AppHeader
|
||||
brand={<img src="/nodedc-logo.svg" alt="NODE.DC" />}
|
||||
brandHref="/"
|
||||
brandLabel="NODEDC MISSION CORE"
|
||||
center={
|
||||
<>
|
||||
@@ -633,18 +632,35 @@ export default function App() {
|
||||
<HeaderNavigation
|
||||
label="Архитектурные блоки пункта управления"
|
||||
value={activeRoot ?? undefined}
|
||||
items={visibleRoots.map((root) => ({ value: root.id, label: root.label }))}
|
||||
items={visibleRoots.map((root) => ({
|
||||
value: root.id,
|
||||
label: environment.settings.headerLabels[root.id],
|
||||
}))}
|
||||
onChange={selectRoot}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
right={
|
||||
<HeaderProfile>
|
||||
<HeaderProfileButton onClick={() => void runtime.refresh()} title="Обновить локальный контур">
|
||||
<span className="api-dot" data-status={runtime.backendStatus} aria-hidden="true" />
|
||||
{backendLabel(runtime.backendStatus)}
|
||||
</HeaderProfileButton>
|
||||
<HeaderAvatar label="DC" />
|
||||
<UserProfileMenu
|
||||
displayName="DC"
|
||||
subtitle="Mission Core"
|
||||
triggerLabel={null}
|
||||
actions={[
|
||||
{
|
||||
id: "refresh",
|
||||
label: "Обновить контур",
|
||||
icon: "refresh",
|
||||
onSelect: () => void runtime.refresh(),
|
||||
},
|
||||
{
|
||||
id: "settings",
|
||||
label: "Настройки",
|
||||
icon: "settings",
|
||||
onSelect: () => setEnvironmentSettingsOpen(true),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</HeaderProfile>
|
||||
}
|
||||
/>
|
||||
@@ -668,6 +684,9 @@ export default function App() {
|
||||
backendStatus={runtime.backendStatus}
|
||||
phase={runtime.state?.phase}
|
||||
message={runtime.state?.message}
|
||||
background={
|
||||
environment.settings.backgrounds[activeRoot ?? "home"]
|
||||
}
|
||||
onOpenObservation={() => openView("spatial-scene")}
|
||||
onOpenDevice={() => openView("local-device")}
|
||||
/>
|
||||
@@ -764,7 +783,7 @@ export default function App() {
|
||||
) : activeDefinition.kind === "datasets" ? (
|
||||
<StatusBadge tone="neutral">Offline evaluation</StatusBadge>
|
||||
) : activeDefinition.kind === "lab-archive" ? (
|
||||
<StatusBadge tone="accent">Лаборатория</StatusBadge>
|
||||
null
|
||||
) : (
|
||||
<StatusBadge tone="warning">Интерфейс готов</StatusBadge>
|
||||
)
|
||||
@@ -821,6 +840,16 @@ export default function App() {
|
||||
) : null}
|
||||
/>
|
||||
|
||||
<EnvironmentSettingsWindow
|
||||
open={environmentSettingsOpen}
|
||||
settings={environment.settings}
|
||||
state={environment.state}
|
||||
error={environment.error}
|
||||
onClose={() => setEnvironmentSettingsOpen(false)}
|
||||
onSave={environment.save}
|
||||
onUpload={environment.upload}
|
||||
/>
|
||||
|
||||
<Window
|
||||
open={sceneWorkspaceActive && sourceWindowOpen}
|
||||
title="Визуальный движок"
|
||||
|
||||
Reference in New Issue
Block a user