enhance ux local server page (#4045)
This commit is contained in:
parent
05019f7236
commit
43eff865ff
@ -1,8 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
|
||||
import { memo, useCallback, useEffect, useState } from 'react'
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react'
|
||||
|
||||
import { Button, useClipboard } from '@janhq/joi'
|
||||
import { Button, ScrollArea, useClipboard } from '@janhq/joi'
|
||||
import { useAtomValue } from 'jotai'
|
||||
|
||||
import { FolderIcon, CheckIcon, CopyIcon } from 'lucide-react'
|
||||
@ -22,6 +22,9 @@ const ServerLogs = (props: ServerLogsProps) => {
|
||||
const { getLogs } = useLogs()
|
||||
const serverEnabled = useAtomValue(serverEnabledAtom)
|
||||
const [logs, setLogs] = useState<string[]>([])
|
||||
const listRef = useRef<HTMLDivElement>(null)
|
||||
const prevScrollTop = useRef(0)
|
||||
const isUserManuallyScrollingUp = useRef(false)
|
||||
|
||||
const updateLogs = useCallback(
|
||||
() =>
|
||||
@ -58,13 +61,45 @@ const ServerLogs = (props: ServerLogsProps) => {
|
||||
|
||||
const clipboard = useClipboard({ timeout: 1000 })
|
||||
|
||||
const handleScroll = useCallback((event: React.UIEvent<HTMLElement>) => {
|
||||
const currentScrollTop = event.currentTarget.scrollTop
|
||||
|
||||
if (prevScrollTop.current > currentScrollTop) {
|
||||
isUserManuallyScrollingUp.current = true
|
||||
} else {
|
||||
const currentScrollTop = event.currentTarget.scrollTop
|
||||
const scrollHeight = event.currentTarget.scrollHeight
|
||||
const clientHeight = event.currentTarget.clientHeight
|
||||
|
||||
if (currentScrollTop + clientHeight >= scrollHeight) {
|
||||
isUserManuallyScrollingUp.current = false
|
||||
}
|
||||
}
|
||||
|
||||
if (isUserManuallyScrollingUp.current === true) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
prevScrollTop.current = currentScrollTop
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (isUserManuallyScrollingUp.current === true || !listRef.current) return
|
||||
const scrollHeight = listRef.current?.scrollHeight ?? 0
|
||||
listRef.current?.scrollTo({
|
||||
top: scrollHeight,
|
||||
behavior: 'instant',
|
||||
})
|
||||
}, [listRef.current?.scrollHeight, isUserManuallyScrollingUp, logs])
|
||||
|
||||
return (
|
||||
<div
|
||||
<ScrollArea
|
||||
ref={listRef}
|
||||
className={twMerge(
|
||||
'p-4 pb-0',
|
||||
!withCopy && 'max-w-[38vw] lg:max-w-[40vw] xl:max-w-[50vw]',
|
||||
'h-[calc(100%-49px)] w-full p-4 py-0',
|
||||
logs.length === 0 && 'mx-auto'
|
||||
)}
|
||||
onScroll={handleScroll}
|
||||
>
|
||||
{withCopy && (
|
||||
<div className="absolute right-2 top-7">
|
||||
@ -107,7 +142,7 @@ const ServerLogs = (props: ServerLogsProps) => {
|
||||
)}
|
||||
<div className="flex h-full w-full flex-col">
|
||||
{logs.length > 0 ? (
|
||||
<code className="inline-block whitespace-break-spaces text-[13px]">
|
||||
<code className="inline-block max-w-[38vw] whitespace-break-spaces text-[13px] lg:max-w-[40vw] xl:max-w-[50vw]">
|
||||
{logs.slice(-limit).map((log, i) => {
|
||||
return (
|
||||
<p key={i} className="my-2 leading-relaxed">
|
||||
@ -256,7 +291,7 @@ const ServerLogs = (props: ServerLogsProps) => {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollArea>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { Button, ScrollArea } from '@janhq/joi'
|
||||
import { Button } from '@janhq/joi'
|
||||
import { CodeIcon, Paintbrush } from 'lucide-react'
|
||||
|
||||
import { InfoIcon } from 'lucide-react'
|
||||
@ -26,8 +26,8 @@ const LocalServerCenterPanel = () => {
|
||||
|
||||
return (
|
||||
<CenterPanelContainer>
|
||||
<div className="flex h-full w-full flex-col overflow-hidden">
|
||||
<div className="sticky top-0 flex items-center justify-between border-b border-[hsla(var(--app-border))] px-4 py-2">
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<div className="sticky top-0 z-10 flex items-center justify-between border-b border-[hsla(var(--app-border))] bg-[hsla(var(--app-bg))] px-4 py-2">
|
||||
<h2 className="font-bold">Server Logs</h2>
|
||||
<div className="space-x-2">
|
||||
<Button
|
||||
@ -72,9 +72,7 @@ const LocalServerCenterPanel = () => {
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<ScrollArea className="h-full w-full">
|
||||
<ServerLogs />
|
||||
</ScrollArea>
|
||||
<ServerLogs />
|
||||
)}
|
||||
</div>
|
||||
</CenterPanelContainer>
|
||||
|
||||
@ -29,6 +29,7 @@ const LocalServerLeftPanel = () => {
|
||||
const [errorRangePort, setErrorRangePort] = useState(false)
|
||||
const [errorPrefix, setErrorPrefix] = useState(false)
|
||||
const [serverEnabled, setServerEnabled] = useAtom(serverEnabledAtom)
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const { startModel, stateModel } = useActiveModel()
|
||||
const selectedModel = useAtomValue(selectedModelAtom)
|
||||
@ -66,6 +67,7 @@ const LocalServerLeftPanel = () => {
|
||||
const onStartServerClick = async () => {
|
||||
if (selectedModel == null) return
|
||||
try {
|
||||
setIsLoading(true)
|
||||
const isStarted = await window.core?.api?.startServer({
|
||||
host,
|
||||
port,
|
||||
@ -79,8 +81,10 @@ const LocalServerLeftPanel = () => {
|
||||
setFirstTimeVisitAPIServer(false)
|
||||
}
|
||||
startModel(selectedModel.id, false).catch((e) => console.error(e))
|
||||
setIsLoading(false)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
setIsLoading(false)
|
||||
toaster({
|
||||
title: `Failed to start server!`,
|
||||
description: 'Please check Server Logs for more details.',
|
||||
@ -93,6 +97,7 @@ const LocalServerLeftPanel = () => {
|
||||
window.core?.api?.stopServer()
|
||||
setServerEnabled(false)
|
||||
setLoadModelError(undefined)
|
||||
setIsLoading(false)
|
||||
}
|
||||
|
||||
const onToggleServer = async () => {
|
||||
@ -117,6 +122,7 @@ const LocalServerLeftPanel = () => {
|
||||
block
|
||||
theme={serverEnabled ? 'destructive' : 'primary'}
|
||||
disabled={
|
||||
isLoading ||
|
||||
stateModel.loading ||
|
||||
errorRangePort ||
|
||||
errorPrefix ||
|
||||
@ -124,7 +130,11 @@ const LocalServerLeftPanel = () => {
|
||||
}
|
||||
onClick={onToggleServer}
|
||||
>
|
||||
{serverEnabled ? 'Stop' : 'Start'} Server
|
||||
{isLoading
|
||||
? 'Starting...'
|
||||
: serverEnabled
|
||||
? 'Stop Server'
|
||||
: 'Start Server'}
|
||||
</Button>
|
||||
{serverEnabled && (
|
||||
<Button variant="soft" asChild className="whitespace-nowrap">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user