39 lines
4.6 KiB
TypeScript
39 lines
4.6 KiB
TypeScript
import { useState } from "react";
|
||
import { ActivityIndicator, Button, Icon, ResourceList, ResourceRow, SettingsCard, StatusBadge } from "@nodedc/ui-react";
|
||
import { environmentSetupAvailable } from "./api";
|
||
import type { useEnvironment } from "./useEnvironment";
|
||
import { TailnetAccess } from "./TailnetAccess";
|
||
import { SystemAccess } from "./SystemAccess";
|
||
|
||
const labels:Record<string,string>={pending:"Ожидает",running:"Выполняется",error:"Ошибка",blocked:"Не выполнено"};
|
||
export function EnvironmentView({environment,failure,success}: {environment:ReturnType<typeof useEnvironment>;failure:(error:unknown)=>void;success:(text:string)=>void}) {
|
||
const {value,pending,running,loading,start}=environment;
|
||
const [adding,setAdding]=useState(false);
|
||
const revision=String(value?.run?.updated_at??0);
|
||
const complete=value?.run?.state==="complete"&&value.run.profile_revision===value.profile.revision;
|
||
return <div className="node-content">
|
||
<SettingsCard title="Настройка окружения" description="Установка и проверка компонентов для работы с бортовым компьютером.">
|
||
<p className="node-note">Сконфигурируйте окружение при первом запуске или повторите проверку после изменений. Приложение установит нужные пакеты, настроит службы и получит системные сведения. Вход в частную сеть и доверенный SSH-ключ подтверждаются ниже.</p>
|
||
<Button onClick={start} disabled={running||!value||!environmentSetupAvailable()}>{running?"Настраиваем…":"Сконфигурировать"}</Button>
|
||
{!environmentSetupAvailable()&&<p className="node-note">Настройка запускается из установленного приложения на БК.</p>}
|
||
{pending&&(!value?.run||value.run.state!=="running")&&<ActivityIndicator label="Подтвердите действие в системном окне. Ожидаем начало настройки…" />}
|
||
{!value?loading?<ActivityIndicator label="Получаем этапы настройки" />:<p className="node-note">Сведения о настройке недоступны. Обновите страницу.</p>:<>
|
||
{!value.available&&<p className="node-note">Журнал предыдущего запуска недоступен. Нажмите «Сконфигурировать» — приложение восстановит доступ и выполнит этапы заново.</p>}
|
||
<ResourceList aria-label="Этапы настройки окружения">{value.profile.steps.map(specification=>{
|
||
const step=value.run?.steps.find(item=>item.id===specification.id);
|
||
const state=step?.state??"pending";
|
||
return <li key={specification.id}><ResourceRow icon={state==="running"?<ActivityIndicator size="compact" />:<Icon name={state==="error"?"alert":"circle"} />} title={specification.label} description={specification.description} metadata={step?.detail} status={state==="complete"?<Icon name="check" label="Этап завершён" />:<StatusBadge tone={state==="error"?"warning":"neutral"}>{labels[state]??"Неизвестно"}</StatusBadge>} /></li>;
|
||
})}</ResourceList>
|
||
{value.run&&!running&&value.run.updated_at>0&&<p className="node-note">Результат проверки от {new Date(value.run.updated_at*1000).toLocaleString("ru-RU")}.</p>}
|
||
{complete&&!running&&<p className="node-note">Системные этапы завершены. Ниже проверьте вход в Tailscale и доверенный ключ для SSH.</p>}
|
||
{value.run?.state==="error"&&!running&&<p className="node-note">Часть этапов не завершена. Исправьте указанные причины и повторите настройку.</p>}
|
||
{value.run?.state==="interrupted"&&<p className="node-note">Предыдущая настройка прервана. Повторный запуск проверит уже выполненные этапы.</p>}
|
||
</>}
|
||
</SettingsCard>
|
||
{!running&&<>
|
||
<SettingsCard title="Доверенное устройство для SSH"><SystemAccess revision={revision} failure={failure} success={success} adding={adding} closeAdd={()=>setAdding(false)} startAdd={()=>setAdding(true)} /></SettingsCard>
|
||
<TailnetAccess failure={failure} revision={revision} />
|
||
</>}
|
||
</div>;
|
||
}
|