* Make thread screen as default screen * Blank state when user have not any model * Cleanup topbar thread screen * Improve style right panel * Add instructions right panel * Styling thread list history * Resolve conflict * Default title new thread * Fix trigger panel sidebar * Make default right panel false when no activethread * Fix CI test * chore: assistant instruction with system prompt * Fix title and blank state explore the hub * Claenup style thread screen and add buble message for assitant * Remove unused import * Styling more menus on thread list and right panel, and make max height textarea 400 pixel * Finished revamp ui thread * Finished system monitor UI * Style box running models * Make animate right panel more smooth * Add status arround textarea for starting model info * Temporary disable hide left panel * chore: system resource monitoring update * copy nits * chore: typo * Reverse icon chevron accordion * Move my models into setting page --------- Co-authored-by: Louis <louis@jan.ai> Co-authored-by: 0xSage <n@pragmatic.vc>
118 lines
4.4 KiB
TypeScript
118 lines
4.4 KiB
TypeScript
import { ScrollArea, Progress, Badge, Button } from '@janhq/uikit'
|
|
|
|
import { useAtomValue } from 'jotai'
|
|
|
|
import { useActiveModel } from '@/hooks/useActiveModel'
|
|
|
|
import { toGigabytes } from '@/utils/converter'
|
|
|
|
import {
|
|
cpuUsageAtom,
|
|
totalRamAtom,
|
|
usedRamAtom,
|
|
} from '@/helpers/atoms/SystemBar.atom'
|
|
|
|
const Column = ['Name', 'Model ID', 'Size', 'Version', 'Action']
|
|
|
|
export default function SystemMonitorScreen() {
|
|
const totalRam = useAtomValue(totalRamAtom)
|
|
const usedRam = useAtomValue(usedRamAtom)
|
|
const cpuUsage = useAtomValue(cpuUsageAtom)
|
|
const { activeModel, stateModel, stopModel } = useActiveModel()
|
|
|
|
return (
|
|
<div className="flex h-full w-full bg-background dark:bg-background/50">
|
|
<ScrollArea className="h-full w-full">
|
|
<div className="h-full p-8" data-test-id="testid-system-monitor">
|
|
<div className="grid grid-cols-2 gap-8 lg:grid-cols-3">
|
|
<div className="rounded-xl border border-border px-8 py-6">
|
|
<div className="flex items-center justify-between">
|
|
<h4 className="text-base font-bold uppercase">
|
|
ram ({Math.round((usedRam / totalRam) * 100)}%)
|
|
</h4>
|
|
<span className="text-xs text-muted-foreground">
|
|
{toGigabytes(usedRam)} GB of {toGigabytes(totalRam)} GB used
|
|
</span>
|
|
</div>
|
|
<div className="mt-2">
|
|
<Progress
|
|
className="mb-2 h-10 rounded-md"
|
|
value={Math.round((usedRam / totalRam) * 100)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
<div className="rounded-xl border border-border px-8 py-6">
|
|
<div className="flex items-center justify-between">
|
|
<h4 className="text-base font-bold uppercase">
|
|
cpu ({cpuUsage}%)
|
|
</h4>
|
|
<span className="text-xs text-muted-foreground">
|
|
{cpuUsage}% of 100%
|
|
</span>
|
|
</div>
|
|
<div className="mt-2">
|
|
<Progress className="mb-2 h-10 rounded-md" value={cpuUsage} />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{activeModel && (
|
|
<div className="mt-8 overflow-hidden rounded-xl border border-border shadow-sm">
|
|
<div className="px-6 py-5">
|
|
<h4 className="text-base font-medium">Running Models</h4>
|
|
</div>
|
|
<div className="relative overflow-x-auto shadow-md">
|
|
<table className="w-full px-8">
|
|
<thead className="w-full border-b border-border bg-secondary">
|
|
<tr>
|
|
{Column.map((col, i) => {
|
|
return (
|
|
<th
|
|
key={i}
|
|
className="px-6 py-2 text-left font-normal last:text-center"
|
|
>
|
|
{col}
|
|
</th>
|
|
)
|
|
})}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td className="px-6 py-2 font-bold">
|
|
{activeModel.name}
|
|
</td>
|
|
<td className="px-6 py-2 font-bold">{activeModel.id}</td>
|
|
<td className="px-6 py-2">
|
|
<Badge themes="secondary">
|
|
{toGigabytes(activeModel.metadata.size)}
|
|
</Badge>
|
|
</td>
|
|
<td className="px-6 py-2">
|
|
<Badge themes="secondary">v{activeModel.version}</Badge>
|
|
</td>
|
|
<td className="px-6 py-2 text-center">
|
|
<Button
|
|
block
|
|
themes={
|
|
stateModel.state === 'stop' ? 'danger' : 'primary'
|
|
}
|
|
className="w-16"
|
|
loading={stateModel.loading}
|
|
onClick={() => stopModel(activeModel.id)}
|
|
>
|
|
Stop
|
|
</Button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</ScrollArea>
|
|
</div>
|
|
)
|
|
}
|