feat: improvement ux for local api server
This commit is contained in:
parent
aeab22f5ab
commit
69ff85f66a
@ -162,7 +162,11 @@ export default function DropdownListSidebar() {
|
|||||||
stateModel.loading && 'pointer-events-none bg-blue-200 text-blue-600'
|
stateModel.loading && 'pointer-events-none bg-blue-200 text-blue-600'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Select value={selectedModel?.id} onValueChange={onValueSelected}>
|
<Select
|
||||||
|
value={selectedModel?.id}
|
||||||
|
onValueChange={onValueSelected}
|
||||||
|
disabled={serverEnabled}
|
||||||
|
>
|
||||||
<SelectTrigger className="relative w-full">
|
<SelectTrigger className="relative w-full">
|
||||||
<SelectValue placeholder="Choose model to start">
|
<SelectValue placeholder="Choose model to start">
|
||||||
{stateModel.loading && (
|
{stateModel.loading && (
|
||||||
|
|||||||
@ -49,6 +49,9 @@ const TopBar = () => {
|
|||||||
case MainViewState.Thread:
|
case MainViewState.Thread:
|
||||||
return activeThread ? activeThread?.title : 'New Thread'
|
return activeThread ? activeThread?.title : 'New Thread'
|
||||||
|
|
||||||
|
case MainViewState.LocalServer:
|
||||||
|
return 'Local API Server'
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return MainViewState[viewStateName]?.replace(/([A-Z])/g, ' $1').trim()
|
return MainViewState[viewStateName]?.replace(/([A-Z])/g, ' $1').trim()
|
||||||
}
|
}
|
||||||
@ -78,34 +81,36 @@ const TopBar = () => {
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="relative w-full">
|
<div className="relative w-full">
|
||||||
<div className="absolute left-16 h-full w-60 border-r border-border">
|
{mainViewState == MainViewState.Thread && (
|
||||||
<div className="flex h-full w-full items-center justify-between">
|
<div className="absolute left-16 h-full w-60 border-r border-border">
|
||||||
<div
|
<div className="flex h-full w-full items-center justify-between">
|
||||||
className={twMerge(
|
<div
|
||||||
'unset-drag cursor-pointer',
|
className={twMerge('unset-drag cursor-pointer')}
|
||||||
mainViewState !== MainViewState.Thread && 'invisible'
|
onClick={() => setShowLeftSideBar((show) => !show)}
|
||||||
)}
|
>
|
||||||
onClick={() => setShowLeftSideBar((show) => !show)}
|
<PanelRightCloseIcon
|
||||||
>
|
size={20}
|
||||||
<PanelRightCloseIcon
|
className={twMerge(
|
||||||
size={20}
|
'ml-4 text-muted-foreground',
|
||||||
className={twMerge(
|
showLeftSideBar && 'rotate-180'
|
||||||
'ml-4 text-muted-foreground',
|
)}
|
||||||
showLeftSideBar && 'rotate-180'
|
/>
|
||||||
)}
|
</div>
|
||||||
/>
|
<div
|
||||||
</div>
|
className="unset-drag cursor-pointer pr-4"
|
||||||
<div
|
onClick={onCreateConversationClick}
|
||||||
className="unset-drag cursor-pointer pr-4"
|
>
|
||||||
onClick={onCreateConversationClick}
|
<PenSquareIcon size={20} className="text-muted-foreground" />
|
||||||
>
|
</div>
|
||||||
<PenSquareIcon size={20} className="text-muted-foreground" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
<div
|
<div
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'absolute left-80 right-10 h-full',
|
'absolute right-10 h-full',
|
||||||
|
mainViewState == MainViewState.Thread
|
||||||
|
? 'left-80'
|
||||||
|
: 'left-16 pl-6',
|
||||||
showing && 'right-80'
|
showing && 'right-80'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
import ScrollToBottom from 'react-scroll-to-bottom'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Switch,
|
Switch,
|
||||||
@ -99,7 +101,7 @@ const LocalServerScreen = () => {
|
|||||||
<div className="space-y-3 px-4">
|
<div className="space-y-3 px-4">
|
||||||
<Button
|
<Button
|
||||||
block
|
block
|
||||||
themes={serverEnabled ? 'danger' : 'success'}
|
themes={serverEnabled ? 'danger' : 'primary'}
|
||||||
disabled={stateModel.loading}
|
disabled={stateModel.loading}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (serverEnabled) {
|
if (serverEnabled) {
|
||||||
@ -135,105 +137,124 @@ const LocalServerScreen = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-4 p-4">
|
<Tooltip>
|
||||||
<div className="flex w-full flex-shrink-0 items-center gap-x-2">
|
<TooltipTrigger asChild>
|
||||||
<Select
|
<div className="space-y-4 p-4">
|
||||||
value={host}
|
<div>
|
||||||
onValueChange={(e) => setHost(e)}
|
<p className="mb-2 block text-sm font-semibold text-zinc-500 dark:text-gray-300">
|
||||||
disabled={serverEnabled}
|
Server Options
|
||||||
>
|
</p>
|
||||||
<SelectTrigger className="w-full">
|
<div className="flex w-full flex-shrink-0 items-center gap-x-2">
|
||||||
<SelectValue />
|
<Select
|
||||||
</SelectTrigger>
|
value={host}
|
||||||
<SelectContent>
|
onValueChange={(e) => setHost(e)}
|
||||||
<SelectItem value="127.0.0.1">127.0.0.1</SelectItem>
|
disabled={serverEnabled}
|
||||||
<SelectItem value="0.0.0.0">0.0.0.0</SelectItem>
|
>
|
||||||
</SelectContent>
|
<SelectTrigger className="w-full">
|
||||||
</Select>
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="127.0.0.1">127.0.0.1</SelectItem>
|
||||||
|
<SelectItem value="0.0.0.0">0.0.0.0</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
|
||||||
<Input
|
<Input
|
||||||
className="w-[60px] flex-shrink-0"
|
className="w-[60px] flex-shrink-0"
|
||||||
value={port}
|
value={port}
|
||||||
onChange={(e) => setPort(e.target.value)}
|
onChange={(e) => setPort(e.target.value)}
|
||||||
maxLength={4}
|
maxLength={4}
|
||||||
disabled={serverEnabled}
|
disabled={serverEnabled}
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label
|
|
||||||
id="cors"
|
|
||||||
className="mb-2 inline-flex items-start gap-x-2 font-bold text-zinc-500 dark:text-gray-300"
|
|
||||||
>
|
|
||||||
Cross-Origin-Resource-Sharing (CORS)
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<InfoIcon
|
|
||||||
size={16}
|
|
||||||
className="mt-0.5 flex-shrink-0 dark:text-gray-500"
|
|
||||||
/>
|
/>
|
||||||
</TooltipTrigger>
|
</div>
|
||||||
<TooltipPortal>
|
</div>
|
||||||
<TooltipContent side="top" className="max-w-[240px]">
|
<div>
|
||||||
<span>
|
<label
|
||||||
CORS (Cross-Origin Resource Sharing) manages resource
|
id="cors"
|
||||||
access on this server from external domains. Enable for
|
className="mb-2 inline-flex items-start gap-x-2 font-bold text-zinc-500 dark:text-gray-300"
|
||||||
secure inter-website communication, regulating data
|
>
|
||||||
sharing to bolster overall security.
|
Cross-Origin-Resource-Sharing (CORS)
|
||||||
</span>
|
<Tooltip>
|
||||||
<TooltipArrow />
|
<TooltipTrigger asChild>
|
||||||
</TooltipContent>
|
<InfoIcon
|
||||||
</TooltipPortal>
|
size={16}
|
||||||
</Tooltip>
|
className="mt-0.5 flex-shrink-0 dark:text-gray-500"
|
||||||
</label>
|
/>
|
||||||
<div className="flex items-center justify-between">
|
</TooltipTrigger>
|
||||||
<Switch
|
<TooltipPortal>
|
||||||
checked={isCorsEnabled}
|
<TooltipContent side="top" className="max-w-[240px]">
|
||||||
onCheckedChange={(e) => setIsCorsEnabled(e)}
|
<span>
|
||||||
name="cors"
|
CORS (Cross-Origin Resource Sharing) manages resource
|
||||||
disabled={serverEnabled}
|
access on this server from external domains. Enable
|
||||||
/>
|
for secure inter-website communication, regulating
|
||||||
</div>
|
data sharing to bolster overall security.
|
||||||
</div>
|
</span>
|
||||||
<div>
|
<TooltipArrow />
|
||||||
<label
|
</TooltipContent>
|
||||||
id="verbose"
|
</TooltipPortal>
|
||||||
className="mb-2 inline-flex items-start gap-x-2 font-bold text-zinc-500 dark:text-gray-300"
|
</Tooltip>
|
||||||
>
|
</label>
|
||||||
Verbose Server Logs
|
<div className="flex items-center justify-between">
|
||||||
<Tooltip>
|
<Switch
|
||||||
<TooltipTrigger asChild>
|
checked={isCorsEnabled}
|
||||||
<InfoIcon
|
onCheckedChange={(e) => setIsCorsEnabled(e)}
|
||||||
size={16}
|
name="cors"
|
||||||
className="mt-0.5 flex-shrink-0 dark:text-gray-500"
|
disabled={serverEnabled}
|
||||||
/>
|
/>
|
||||||
</TooltipTrigger>
|
</div>
|
||||||
<TooltipPortal>
|
</div>
|
||||||
<TooltipContent side="top" className="max-w-[240px]">
|
<div>
|
||||||
<span>
|
<label
|
||||||
Verbose Server Logs provide extensive details about server
|
id="verbose"
|
||||||
activities. Enable to capture thorough records, aiding in
|
className="mb-2 inline-flex items-start gap-x-2 font-bold text-zinc-500 dark:text-gray-300"
|
||||||
troubleshooting and monitoring server performance
|
>
|
||||||
effectively.
|
Verbose Server Logs
|
||||||
</span>
|
<Tooltip>
|
||||||
<TooltipArrow />
|
<TooltipTrigger asChild>
|
||||||
</TooltipContent>
|
<InfoIcon
|
||||||
</TooltipPortal>
|
size={16}
|
||||||
</Tooltip>
|
className="mt-0.5 flex-shrink-0 dark:text-gray-500"
|
||||||
</label>
|
/>
|
||||||
<div className="flex items-center justify-between">
|
</TooltipTrigger>
|
||||||
<Switch
|
<TooltipPortal>
|
||||||
checked={isVerboseEnabled}
|
<TooltipContent side="top" className="max-w-[240px]">
|
||||||
onCheckedChange={(e) => setIsVerboseEnabled(e)}
|
<span>
|
||||||
name="verbose"
|
Verbose Server Logs provide extensive details about
|
||||||
disabled={serverEnabled}
|
server activities. Enable to capture thorough records,
|
||||||
/>
|
aiding in troubleshooting and monitoring server
|
||||||
|
performance effectively.
|
||||||
|
</span>
|
||||||
|
<TooltipArrow />
|
||||||
|
</TooltipContent>
|
||||||
|
</TooltipPortal>
|
||||||
|
</Tooltip>
|
||||||
|
</label>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Switch
|
||||||
|
checked={isVerboseEnabled}
|
||||||
|
onCheckedChange={(e) => setIsVerboseEnabled(e)}
|
||||||
|
name="verbose"
|
||||||
|
disabled={serverEnabled}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</TooltipTrigger>
|
||||||
</div>
|
<TooltipPortal>
|
||||||
|
{serverEnabled && (
|
||||||
|
<TooltipContent side="bottom" className="max-w-[200px]">
|
||||||
|
<span>
|
||||||
|
Settings cannot be modified while the server is running
|
||||||
|
</span>
|
||||||
|
<TooltipArrow />
|
||||||
|
</TooltipContent>
|
||||||
|
)}
|
||||||
|
</TooltipPortal>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Middle Bar */}
|
{/* Middle Bar */}
|
||||||
<div className="relative flex h-full w-full flex-col overflow-auto bg-background">
|
<ScrollToBottom className="relative flex h-full w-full flex-col overflow-auto bg-background">
|
||||||
<div className="sticky top-0 flex items-center justify-between bg-zinc-100 px-4 py-2 dark:bg-secondary/30">
|
<div className="sticky top-0 flex items-center justify-between bg-zinc-100 px-4 py-2 dark:bg-secondary/30">
|
||||||
<h2 className="font-bold">Server Logs</h2>
|
<h2 className="font-bold">Server Logs</h2>
|
||||||
<div className="space-x-2">
|
<div className="space-x-2">
|
||||||
@ -279,8 +300,8 @@ const LocalServerScreen = () => {
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h6 className="font-medium text-black">
|
<h6 className="font-medium text-black">
|
||||||
You cannot chat with your assistant while the server is
|
Once you start the server, you cannot chat with your
|
||||||
running.
|
assistant.
|
||||||
</h6>
|
</h6>
|
||||||
<Button
|
<Button
|
||||||
className="mt-4"
|
className="mt-4"
|
||||||
@ -298,7 +319,7 @@ const LocalServerScreen = () => {
|
|||||||
) : (
|
) : (
|
||||||
<Logs />
|
<Logs />
|
||||||
)}
|
)}
|
||||||
</div>
|
</ScrollToBottom>
|
||||||
|
|
||||||
{/* Right bar */}
|
{/* Right bar */}
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -175,11 +175,17 @@ export default function RowModel(props: RowModelProps) {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="flex cursor-pointer items-center space-x-2 px-4 py-2 hover:bg-secondary"
|
className={twMerge(
|
||||||
|
'flex cursor-pointer items-center space-x-2 px-4 py-2 hover:bg-secondary',
|
||||||
|
serverEnabled &&
|
||||||
|
'pointer-events-none cursor-not-allowed opacity-40'
|
||||||
|
)}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
await stopModel()
|
if (serverEnabled) {
|
||||||
deleteModel(props.data)
|
await stopModel()
|
||||||
|
deleteModel(props.data)
|
||||||
|
}
|
||||||
}, 500)
|
}, 500)
|
||||||
setMore(false)
|
setMore(false)
|
||||||
}}
|
}}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user