fix: gpu hardware state (#4650)
* fix: gpu hardware state * chore: cleanup state * chore: clear state
This commit is contained in:
parent
7a6890bd7f
commit
dde260e723
@ -509,61 +509,61 @@ __metadata:
|
|||||||
|
|
||||||
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension":
|
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension":
|
||||||
version: 0.1.10
|
version: 0.1.10
|
||||||
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=2e50a2&locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension"
|
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=429572&locator=%40janhq%2Fassistant-extension%40workspace%3Aassistant-extension"
|
||||||
dependencies:
|
dependencies:
|
||||||
rxjs: "npm:^7.8.1"
|
rxjs: "npm:^7.8.1"
|
||||||
ulidx: "npm:^2.3.0"
|
ulidx: "npm:^2.3.0"
|
||||||
checksum: 10c0/92904b534f4f82c31effd9eade0f8685b87165e28f0c3ba3a0c18a6a0a21bf21ee769a98c562c4ba7488ceb1238e2dacce2bb2f729c1bdd84ad44054fb985da0
|
checksum: 10c0/18b8ca8795ccf2c89e2225668ce2824e4ce7b32872764a739155d2b68a773676188186d721e70dbcf2605bb28697b97d6c01348d34bc440e829087ebd6a3158c
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension":
|
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension":
|
||||||
version: 0.1.10
|
version: 0.1.10
|
||||||
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=2e50a2&locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension"
|
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=429572&locator=%40janhq%2Fconversational-extension%40workspace%3Aconversational-extension"
|
||||||
dependencies:
|
dependencies:
|
||||||
rxjs: "npm:^7.8.1"
|
rxjs: "npm:^7.8.1"
|
||||||
ulidx: "npm:^2.3.0"
|
ulidx: "npm:^2.3.0"
|
||||||
checksum: 10c0/92904b534f4f82c31effd9eade0f8685b87165e28f0c3ba3a0c18a6a0a21bf21ee769a98c562c4ba7488ceb1238e2dacce2bb2f729c1bdd84ad44054fb985da0
|
checksum: 10c0/18b8ca8795ccf2c89e2225668ce2824e4ce7b32872764a739155d2b68a773676188186d721e70dbcf2605bb28697b97d6c01348d34bc440e829087ebd6a3158c
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fengine-management-extension%40workspace%3Aengine-management-extension":
|
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fengine-management-extension%40workspace%3Aengine-management-extension":
|
||||||
version: 0.1.10
|
version: 0.1.10
|
||||||
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=2e50a2&locator=%40janhq%2Fengine-management-extension%40workspace%3Aengine-management-extension"
|
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=429572&locator=%40janhq%2Fengine-management-extension%40workspace%3Aengine-management-extension"
|
||||||
dependencies:
|
dependencies:
|
||||||
rxjs: "npm:^7.8.1"
|
rxjs: "npm:^7.8.1"
|
||||||
ulidx: "npm:^2.3.0"
|
ulidx: "npm:^2.3.0"
|
||||||
checksum: 10c0/92904b534f4f82c31effd9eade0f8685b87165e28f0c3ba3a0c18a6a0a21bf21ee769a98c562c4ba7488ceb1238e2dacce2bb2f729c1bdd84ad44054fb985da0
|
checksum: 10c0/18b8ca8795ccf2c89e2225668ce2824e4ce7b32872764a739155d2b68a773676188186d721e70dbcf2605bb28697b97d6c01348d34bc440e829087ebd6a3158c
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fhardware-management-extension%40workspace%3Ahardware-management-extension":
|
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fhardware-management-extension%40workspace%3Ahardware-management-extension":
|
||||||
version: 0.1.10
|
version: 0.1.10
|
||||||
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=2e50a2&locator=%40janhq%2Fhardware-management-extension%40workspace%3Ahardware-management-extension"
|
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=429572&locator=%40janhq%2Fhardware-management-extension%40workspace%3Ahardware-management-extension"
|
||||||
dependencies:
|
dependencies:
|
||||||
rxjs: "npm:^7.8.1"
|
rxjs: "npm:^7.8.1"
|
||||||
ulidx: "npm:^2.3.0"
|
ulidx: "npm:^2.3.0"
|
||||||
checksum: 10c0/92904b534f4f82c31effd9eade0f8685b87165e28f0c3ba3a0c18a6a0a21bf21ee769a98c562c4ba7488ceb1238e2dacce2bb2f729c1bdd84ad44054fb985da0
|
checksum: 10c0/18b8ca8795ccf2c89e2225668ce2824e4ce7b32872764a739155d2b68a773676188186d721e70dbcf2605bb28697b97d6c01348d34bc440e829087ebd6a3158c
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Finference-cortex-extension%40workspace%3Ainference-cortex-extension":
|
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Finference-cortex-extension%40workspace%3Ainference-cortex-extension":
|
||||||
version: 0.1.10
|
version: 0.1.10
|
||||||
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=2e50a2&locator=%40janhq%2Finference-cortex-extension%40workspace%3Ainference-cortex-extension"
|
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=429572&locator=%40janhq%2Finference-cortex-extension%40workspace%3Ainference-cortex-extension"
|
||||||
dependencies:
|
dependencies:
|
||||||
rxjs: "npm:^7.8.1"
|
rxjs: "npm:^7.8.1"
|
||||||
ulidx: "npm:^2.3.0"
|
ulidx: "npm:^2.3.0"
|
||||||
checksum: 10c0/92904b534f4f82c31effd9eade0f8685b87165e28f0c3ba3a0c18a6a0a21bf21ee769a98c562c4ba7488ceb1238e2dacce2bb2f729c1bdd84ad44054fb985da0
|
checksum: 10c0/18b8ca8795ccf2c89e2225668ce2824e4ce7b32872764a739155d2b68a773676188186d721e70dbcf2605bb28697b97d6c01348d34bc440e829087ebd6a3158c
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fmodel-extension%40workspace%3Amodel-extension":
|
"@janhq/core@file:../../core/package.tgz::locator=%40janhq%2Fmodel-extension%40workspace%3Amodel-extension":
|
||||||
version: 0.1.10
|
version: 0.1.10
|
||||||
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=2e50a2&locator=%40janhq%2Fmodel-extension%40workspace%3Amodel-extension"
|
resolution: "@janhq/core@file:../../core/package.tgz#../../core/package.tgz::hash=429572&locator=%40janhq%2Fmodel-extension%40workspace%3Amodel-extension"
|
||||||
dependencies:
|
dependencies:
|
||||||
rxjs: "npm:^7.8.1"
|
rxjs: "npm:^7.8.1"
|
||||||
ulidx: "npm:^2.3.0"
|
ulidx: "npm:^2.3.0"
|
||||||
checksum: 10c0/92904b534f4f82c31effd9eade0f8685b87165e28f0c3ba3a0c18a6a0a21bf21ee769a98c562c4ba7488ceb1238e2dacce2bb2f729c1bdd84ad44054fb985da0
|
checksum: 10c0/18b8ca8795ccf2c89e2225668ce2824e4ce7b32872764a739155d2b68a773676188186d721e70dbcf2605bb28697b97d6c01348d34bc440e829087ebd6a3158c
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import * as React from 'react'
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
|
||||||
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd'
|
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd'
|
||||||
import { Gpu } from '@janhq/core'
|
|
||||||
import { Progress, ScrollArea, Switch } from '@janhq/joi'
|
import { Progress, ScrollArea, Switch } from '@janhq/joi'
|
||||||
import { useAtom, useAtomValue } from 'jotai'
|
import { useAtom, useAtomValue } from 'jotai'
|
||||||
import { atomWithStorage } from 'jotai/utils'
|
import { atomWithStorage } from 'jotai/utils'
|
||||||
@ -20,19 +20,24 @@ import {
|
|||||||
|
|
||||||
import { toGibibytes } from '@/utils/converter'
|
import { toGibibytes } from '@/utils/converter'
|
||||||
|
|
||||||
|
import { utilizedMemory } from '@/utils/memory'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
cpuUsageAtom,
|
cpuUsageAtom,
|
||||||
ramUtilitizedAtom,
|
ramUtilitizedAtom,
|
||||||
totalRamAtom,
|
totalRamAtom,
|
||||||
usedRamAtom,
|
usedRamAtom,
|
||||||
|
gpusAtom,
|
||||||
} from '@/helpers/atoms/SystemBar.atom'
|
} from '@/helpers/atoms/SystemBar.atom'
|
||||||
|
|
||||||
const gpusAtom = atomWithStorage<Gpu[]>('gpus', [], undefined, {
|
const orderGpusAtom = atomWithStorage<any>('orderGpus', [], undefined, {
|
||||||
getOnInit: true,
|
getOnInit: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const Hardware = () => {
|
const Hardware = () => {
|
||||||
const { hardware } = useGetHardwareInfo()
|
const { hardware, mutate } = useGetHardwareInfo()
|
||||||
|
const [isActivatingGpu, setIsActivatingGpu] = useState<Set<string>>(new Set())
|
||||||
|
|
||||||
const [openPanels, setOpenPanels] = useState<Record<number, boolean>>({})
|
const [openPanels, setOpenPanels] = useState<Record<number, boolean>>({})
|
||||||
|
|
||||||
const cpuUsage = useAtomValue(cpuUsageAtom)
|
const cpuUsage = useAtomValue(cpuUsageAtom)
|
||||||
@ -40,7 +45,9 @@ const Hardware = () => {
|
|||||||
const usedRam = useAtomValue(usedRamAtom)
|
const usedRam = useAtomValue(usedRamAtom)
|
||||||
const ramUtilitized = useAtomValue(ramUtilitizedAtom)
|
const ramUtilitized = useAtomValue(ramUtilitizedAtom)
|
||||||
|
|
||||||
const [gpus, setGpus] = useAtom<Gpu[]>(gpusAtom)
|
const [gpus, setGpus] = useAtom(gpusAtom)
|
||||||
|
|
||||||
|
const [orderGpus, setOrderGpus] = useAtom(orderGpusAtom)
|
||||||
|
|
||||||
const togglePanel = (index: number) => {
|
const togglePanel = (index: number) => {
|
||||||
setOpenPanels((prev) => ({
|
setOpenPanels((prev) => ({
|
||||||
@ -51,16 +58,18 @@ const Hardware = () => {
|
|||||||
|
|
||||||
// Handle switch toggle for GPU activation
|
// Handle switch toggle for GPU activation
|
||||||
const handleSwitchChange = async (id: string, isActive: boolean) => {
|
const handleSwitchChange = async (id: string, isActive: boolean) => {
|
||||||
|
setIsActivatingGpu((prev) => new Set(prev).add(id))
|
||||||
|
|
||||||
const updatedGpus = gpus.map((gpu) =>
|
const updatedGpus = gpus.map((gpu) =>
|
||||||
gpu.id === id ? { ...gpu, activated: isActive } : gpu
|
gpu.id === id ? { ...gpu, activated: isActive } : gpu
|
||||||
)
|
)
|
||||||
setGpus(updatedGpus)
|
|
||||||
// Call the API to update the active GPUs
|
// Call the API to update the active GPUs
|
||||||
try {
|
try {
|
||||||
const activeGpuIds = updatedGpus
|
const activeGpuIds = updatedGpus
|
||||||
.filter((gpu) => gpu.activated)
|
.filter((gpu: any) => gpu.activated)
|
||||||
.map((gpu) => Number(gpu.id))
|
.map((gpu: any) => Number(gpu.id))
|
||||||
await setActiveGpus({ gpus: activeGpuIds })
|
await setActiveGpus({ gpus: activeGpuIds })
|
||||||
|
mutate()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to update active GPUs:', error)
|
console.error('Failed to update active GPUs:', error)
|
||||||
}
|
}
|
||||||
@ -71,23 +80,36 @@ const Hardware = () => {
|
|||||||
const reorderedGpus = Array.from(gpus)
|
const reorderedGpus = Array.from(gpus)
|
||||||
const [movedGpu] = reorderedGpus.splice(result.source.index, 1)
|
const [movedGpu] = reorderedGpus.splice(result.source.index, 1)
|
||||||
reorderedGpus.splice(result.destination.index, 0, movedGpu)
|
reorderedGpus.splice(result.destination.index, 0, movedGpu)
|
||||||
setGpus(reorderedGpus) // Update the atom, which persists to localStorage
|
|
||||||
|
setGpus(reorderedGpus)
|
||||||
|
setOrderGpus(reorderedGpus.map((gpu) => gpu.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (hardware?.gpus) {
|
if (hardware?.gpus) {
|
||||||
setGpus((prevGpus) => {
|
setGpus((prevGpus: any) => {
|
||||||
// Create a map of existing GPUs by UUID for quick lookup
|
// Create a map of existing GPUs by UUID for quick lookup
|
||||||
const gpuMap = new Map(prevGpus.map((gpu) => [gpu.uuid, gpu]))
|
const gpuMap = new Map(prevGpus.map((gpu: any) => [gpu.uuid, gpu]))
|
||||||
|
|
||||||
// Update existing GPUs or add new ones
|
// Update existing GPUs or add new ones
|
||||||
const updatedGpus = hardware.gpus.map((newGpu) => {
|
const updatedGpus = hardware.gpus.map((newGpu) => {
|
||||||
const existingGpu = gpuMap.get(newGpu.uuid)
|
const existingGpu: any = gpuMap.get(newGpu.uuid)
|
||||||
|
|
||||||
if (existingGpu) {
|
if (existingGpu) {
|
||||||
// Update the GPU properties while keeping the original order
|
// Update the GPU properties while keeping the original order
|
||||||
|
|
||||||
|
if (existingGpu.activated !== newGpu.activated) {
|
||||||
|
setIsActivatingGpu((prev) => {
|
||||||
|
const updated = new Set(prev)
|
||||||
|
updated.delete(existingGpu.id)
|
||||||
|
updated.clear()
|
||||||
|
return updated
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...existingGpu,
|
...existingGpu,
|
||||||
|
activated: newGpu.activated,
|
||||||
free_vram: newGpu.free_vram,
|
free_vram: newGpu.free_vram,
|
||||||
total_vram: newGpu.total_vram,
|
total_vram: newGpu.total_vram,
|
||||||
}
|
}
|
||||||
@ -100,7 +122,8 @@ const Hardware = () => {
|
|||||||
// Append GPUs from the previous state that are not in the hardware.gpus
|
// Append GPUs from the previous state that are not in the hardware.gpus
|
||||||
// This preserves user-reordered GPUs that aren't present in the new data
|
// This preserves user-reordered GPUs that aren't present in the new data
|
||||||
const remainingGpus = prevGpus.filter(
|
const remainingGpus = prevGpus.filter(
|
||||||
(prevGpu) => !hardware.gpus?.some((gpu) => gpu.uuid === prevGpu.uuid)
|
(prevGpu: any) =>
|
||||||
|
!hardware.gpus?.some((gpu) => gpu.uuid === prevGpu.uuid)
|
||||||
)
|
)
|
||||||
|
|
||||||
return [...updatedGpus, ...remainingGpus]
|
return [...updatedGpus, ...remainingGpus]
|
||||||
@ -202,133 +225,154 @@ const Hardware = () => {
|
|||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
className="mt-4"
|
className="mt-4"
|
||||||
>
|
>
|
||||||
{gpus.map((item, i) => (
|
{gpus
|
||||||
<Draggable key={i} draggableId={String(i)} index={i}>
|
.sort((a, b) => {
|
||||||
{(provided, snapshot) => (
|
const orderA = orderGpus.indexOf(a.id)
|
||||||
<div
|
const orderB = orderGpus.indexOf(b.id)
|
||||||
ref={provided.innerRef}
|
return orderA - orderB
|
||||||
{...provided.draggableProps}
|
})
|
||||||
{...provided.dragHandleProps}
|
.map((item: any, i) => {
|
||||||
className={twMerge(
|
const gpuUtilization = utilizedMemory(
|
||||||
'cursor-pointer border border-[hsla(var(--app-border))] bg-[hsla(var(--tertiary-bg))] p-4 first:rounded-t-lg last:rounded-b-lg',
|
item.free_vram,
|
||||||
gpus.length > 1 && 'last:rounded-t-none',
|
item.total_vram
|
||||||
snapshot.isDragging
|
)
|
||||||
? 'border-b'
|
const isLoading = isActivatingGpu.has(item.id)
|
||||||
: 'border-b-0 last:border-b'
|
|
||||||
)}
|
return (
|
||||||
onClick={() => togglePanel(i)}
|
<Draggable
|
||||||
|
key={i}
|
||||||
|
draggableId={String(i)}
|
||||||
|
index={i}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col items-start justify-start gap-4 sm:flex-row sm:items-center sm:justify-between">
|
{(provided, snapshot) => (
|
||||||
<div className="flex w-full items-center justify-between">
|
<div
|
||||||
<div className="flex h-full flex-shrink-0 items-center gap-2">
|
ref={provided.innerRef}
|
||||||
<GripVerticalIcon
|
{...provided.draggableProps}
|
||||||
size={14}
|
{...provided.dragHandleProps}
|
||||||
className="text-[hsla(var(--text-tertiary))]"
|
className={twMerge(
|
||||||
/>
|
'cursor-pointer border border-[hsla(var(--app-border))] bg-[hsla(var(--tertiary-bg))] p-4 first:rounded-t-lg last:rounded-b-lg',
|
||||||
<div
|
gpus.length > 1 && 'last:rounded-t-none',
|
||||||
className={twMerge(
|
snapshot.isDragging
|
||||||
'h-2 w-2 rounded-full',
|
? 'border-b'
|
||||||
item.activated
|
: 'border-b-0 last:border-b'
|
||||||
? 'bg-green-400'
|
)}
|
||||||
: 'bg-neutral-300'
|
onClick={() => togglePanel(i)}
|
||||||
)}
|
>
|
||||||
/>
|
<div className="flex flex-col items-start justify-start gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||||
<h6 title={item.name}>{item.name}</h6>
|
<div className="flex w-full items-center justify-between">
|
||||||
</div>
|
<div className="flex h-full flex-shrink-0 items-center gap-2">
|
||||||
<div className="flex flex-shrink-0 items-end gap-4">
|
<GripVerticalIcon
|
||||||
{item.activated && (
|
size={14}
|
||||||
<div className="flex w-40 items-center gap-3">
|
className="text-[hsla(var(--text-tertiary))]"
|
||||||
<Progress
|
|
||||||
value={Math.round(
|
|
||||||
((Number(item.total_vram) -
|
|
||||||
Number(item.free_vram)) /
|
|
||||||
Number(item.total_vram)) *
|
|
||||||
100
|
|
||||||
)}
|
|
||||||
size="small"
|
|
||||||
className="w-full"
|
|
||||||
/>
|
/>
|
||||||
<span className="font-medium">
|
<div
|
||||||
{Math.round(
|
className={twMerge(
|
||||||
((Number(item.total_vram) -
|
'h-2 w-2 rounded-full',
|
||||||
Number(item.free_vram)) /
|
item.activated
|
||||||
Number(item.total_vram)) *
|
? 'bg-green-400'
|
||||||
100
|
: 'bg-neutral-300'
|
||||||
).toFixed()}
|
)}
|
||||||
%
|
/>
|
||||||
|
<h6 title={item.name}>{item.name}</h6>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-shrink-0 items-end gap-4">
|
||||||
|
{item.activated && (
|
||||||
|
<div className="flex w-40 items-center gap-3">
|
||||||
|
<Progress
|
||||||
|
value={gpuUtilization}
|
||||||
|
size="small"
|
||||||
|
className="w-full"
|
||||||
|
/>
|
||||||
|
<span className="font-medium">
|
||||||
|
{gpuUtilization}%
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="flex justify-end gap-2 text-xs text-[hsla(var(--text-secondary))]">
|
||||||
|
{item.activated && (
|
||||||
|
<span>
|
||||||
|
{(
|
||||||
|
(Number(item.total_vram) -
|
||||||
|
Number(item.free_vram)) /
|
||||||
|
1024
|
||||||
|
).toFixed(2)}
|
||||||
|
GB /{' '}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
<span>
|
||||||
|
{(
|
||||||
|
Number(item.total_vram) / 1024
|
||||||
|
).toFixed(2)}
|
||||||
|
GB
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
checked={item.activated}
|
||||||
|
className={twMerge(
|
||||||
|
isLoading && 'pointer-events-none'
|
||||||
|
)}
|
||||||
|
disabled={
|
||||||
|
Boolean(isActivatingGpu.size) &&
|
||||||
|
!isLoading
|
||||||
|
}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleSwitchChange(
|
||||||
|
item.id,
|
||||||
|
e.target.checked
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{isLoading && (
|
||||||
|
<div className="ml-2 h-4 w-4 animate-spin rounded-full border-t-2 border-solid border-blue-500" />
|
||||||
|
)}
|
||||||
|
|
||||||
|
<ChevronDownIcon
|
||||||
|
size={14}
|
||||||
|
className={twMerge(
|
||||||
|
'relative z-10 transform cursor-pointer transition-transform',
|
||||||
|
openPanels[i]
|
||||||
|
? 'rotate-180'
|
||||||
|
: 'rotate-0'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{openPanels[i] && (
|
||||||
|
<div className="space-y-4 p-4 pb-0 text-[hsla(var(--text-secondary))]">
|
||||||
|
<div className="flex">
|
||||||
|
<div className="w-[200px]">
|
||||||
|
Driver Version
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
{
|
||||||
|
item.additional_information
|
||||||
|
?.driver_version
|
||||||
|
}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
<div className="flex">
|
||||||
|
<div className="w-[200px]">
|
||||||
<div className="flex justify-end gap-2 text-xs text-[hsla(var(--text-secondary))]">
|
Compute Capability
|
||||||
{item.activated && (
|
</div>
|
||||||
<span>
|
<span>
|
||||||
{(
|
{
|
||||||
(Number(item.total_vram) -
|
item.additional_information
|
||||||
Number(item.free_vram)) /
|
?.compute_cap
|
||||||
1024
|
}
|
||||||
).toFixed(2)}
|
|
||||||
GB /{' '}
|
|
||||||
</span>
|
</span>
|
||||||
)}
|
</div>
|
||||||
<span>
|
|
||||||
{(
|
|
||||||
Number(item.total_vram) / 1024
|
|
||||||
).toFixed(2)}
|
|
||||||
GB
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<Switch
|
|
||||||
checked={item.activated}
|
|
||||||
onChange={(e) =>
|
|
||||||
handleSwitchChange(
|
|
||||||
item.id,
|
|
||||||
e.target.checked
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ChevronDownIcon
|
|
||||||
size={14}
|
|
||||||
className={twMerge(
|
|
||||||
'relative z-10 transform cursor-pointer transition-transform',
|
|
||||||
openPanels[i]
|
|
||||||
? 'rotate-180'
|
|
||||||
: 'rotate-0'
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{openPanels[i] && (
|
|
||||||
<div className="space-y-4 p-4 pb-0 text-[hsla(var(--text-secondary))]">
|
|
||||||
<div className="flex">
|
|
||||||
<div className="w-[200px]">
|
|
||||||
Driver Version
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
{
|
|
||||||
item.additional_information
|
|
||||||
?.driver_version
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex">
|
|
||||||
<div className="w-[200px]">
|
|
||||||
Compute Capability
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
{item.additional_information?.compute_cap}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</Draggable>
|
||||||
)}
|
)
|
||||||
</Draggable>
|
})}
|
||||||
))}
|
|
||||||
{provided.placeholder}
|
{provided.placeholder}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user