26 lines
3.9 KiB
TypeScript
26 lines
3.9 KiB
TypeScript
import type {McpPollStorageCapacity} from "@mmapp/contracts/mcp"
|
|
import {Badge} from "@/components/reui/badge"
|
|
import {Button} from "@/components/ui/button"
|
|
|
|
export function PollStorageCapacity({capacity,loading,refresh}:{capacity?:McpPollStorageCapacity;loading:boolean;refresh:()=>void}){
|
|
const observed=capacity?.status==="observed"?capacity:undefined
|
|
const ownerFull=observed?.owner.remaining===0,globalFull=observed?.global.exhausted===true
|
|
const full=ownerFull||globalFull
|
|
return <section aria-label="Журнал полных опросов" className="flex flex-col gap-3 rounded-lg border p-4">
|
|
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
<h3 className="font-medium">Журнал полных опросов</h3>
|
|
<div className="flex items-center gap-2"><Badge variant={!observed?"info-light":full?"warning-light":"success-light"}>{loading?"Загрузка":!observed?"Нет данных":full?"Квота заполнена":"Квота не заполнена"}</Badge><Button size="sm" variant="outline" onClick={refresh}>Обновить статус</Button></div>
|
|
</div>
|
|
{observed?<>
|
|
<dl className="grid gap-3 text-sm sm:grid-cols-2">
|
|
<div><dt className="text-muted-foreground">Ваши полные журналы</dt><dd className="font-medium tabular-nums">{observed.owner.used} / {observed.owner.limit}<span className="ml-2 font-normal text-muted-foreground">Осталось: {observed.owner.remaining}</span></dd></div>
|
|
<div><dt className="text-muted-foreground">Полные журналы приложения</dt><dd className="font-medium tabular-nums">{observed.global.usage?<>{observed.global.usage.used} / {observed.global.usage.limit}<span className="ml-2 font-normal text-muted-foreground">Осталось: {observed.global.usage.remaining}</span></>:globalFull?"Заполнена":"Не заполнена"}</dd></div>
|
|
</dl>
|
|
{full&&<p role="alert" className="text-sm">{ownerFull&&globalFull?"Личная и общая квоты журнала заполнены.":ownerFull?"Личная квота журнала заполнена.":"Общая квота журнала заполнена."} Новый полный опрос не получит место. После безопасного архивирования или очистки по сроку хранения место может освободиться. Неизвестный результат сохраняет резерв; повторные попытки его не освобождают.</p>}
|
|
<p className="text-sm text-muted-foreground">Счётчик учитывает резерв под выполнение и журналы, ожидающие архивирования. Архив сохраняет все исходные записи и продолжает занимать место. Поэтому остаток зависит и от объёма сохранённой истории.</p>
|
|
<p className="text-sm text-muted-foreground">Срок хранения новых записей: {observed.retentionDays} дн. Существующие записи могут храниться дольше. Архивирование сохраняет исходный срок; очистка учитывает завершение операции, истечение допуска и защитный интервал.</p>
|
|
<p className="text-xs text-muted-foreground">Состояние показано на момент обновления. Окончательный допуск проверяется при запуске.</p>
|
|
</>:<p role="status" className="text-sm text-muted-foreground">{loading?"Проверяем заполнение журнала…":"Заполнение журнала сейчас недоступно. Свободное место не подтверждено; обновите статус позже."}</p>}
|
|
</section>
|
|
}
|