Show alert when user first time visit api server

This commit is contained in:
Faisal Amir 2024-01-16 23:16:48 +07:00
parent 2f417ef5db
commit 14fc686d50
4 changed files with 131 additions and 35 deletions

View File

@ -17,6 +17,8 @@ const SelectGroup = SelectPrimitive.Group
const SelectValue = SelectPrimitive.Value const SelectValue = SelectPrimitive.Value
const SelectPortal = SelectPrimitive.Portal
const SelectTrigger = React.forwardRef< const SelectTrigger = React.forwardRef<
React.ElementRef<typeof SelectPrimitive.Trigger>, React.ElementRef<typeof SelectPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
@ -129,6 +131,7 @@ export {
Select, Select,
SelectGroup, SelectGroup,
SelectValue, SelectValue,
SelectPortal,
SelectTrigger, SelectTrigger,
SelectContent, SelectContent,
SelectLabel, SelectLabel,

View File

@ -6,6 +6,7 @@ import {
Select, Select,
SelectContent, SelectContent,
SelectGroup, SelectGroup,
SelectPortal,
SelectItem, SelectItem,
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
@ -66,6 +67,7 @@ export default function DropdownListSidebar() {
}, []) }, [])
const { recommendedModel, downloadedModels } = useRecommendedModel() const { recommendedModel, downloadedModels } = useRecommendedModel()
const [first, setfirst] = useState(false)
const selectedName = const selectedName =
downloadedModels.filter((x) => x.id === selectedModel?.id)[0]?.name ?? '' downloadedModels.filter((x) => x.id === selectedModel?.id)[0]?.name ?? ''
@ -147,20 +149,18 @@ export default function DropdownListSidebar() {
return ( return (
<> <>
<Select value={selectedModel?.id} onValueChange={onValueSelected}> <Select value={selectedModel?.id} onValueChange={onValueSelected}>
<div className="relative">
<Select value={selected?.id} onValueChange={onValueSelected}>
<SelectTrigger className="w-full"> <SelectTrigger className="w-full">
<SelectValue placeholder="Choose model to start"> <SelectValue placeholder="Choose model to start">
{selectedName} {selectedName}
</SelectValue> </SelectValue>
</SelectTrigger> </SelectTrigger>
<SelectContent className="right-2 block w-full min-w-[450px] pr-0"> <SelectPortal>
<div className="flex w-full items-center space-x-2 px-4 py-2"> <SelectContent className="right-2 block w-full min-w-[450px] pr-0">
<MonitorIcon size={20} className="text-muted-foreground" /> <div className="flex w-full items-center space-x-2 px-4 py-2">
<span>Local</span> <MonitorIcon size={20} className="text-muted-foreground" />
</div> <span>Local</span>
<div className="border-b border-border" />
{downloadedModels.length === 0 ? (
<div className="px-4 py-2">
<p>{`Oops, you don't have a model yet.`}</p>
</div> </div>
) : ( ) : (
<SelectGroup> <SelectGroup>
@ -181,26 +181,67 @@ export default function DropdownListSidebar() {
{x.engine == InferenceEngine.nitro && ( {x.engine == InferenceEngine.nitro && (
<ModelLabel size={x.metadata.size} /> <ModelLabel size={x.metadata.size} />
)} )}
<div className="border-b border-border" />
{downloadedModels.length === 0 ? (
<div className="px-4 py-2">
<p>{`Oops, you don't have a model yet.`}</p>
</div>
) : (
<SelectGroup>
{downloadedModels.map((x, i) => (
<SelectItem
key={i}
value={x.id}
className={twMerge(x.id === selected?.id && 'bg-secondary')}
>
<div className="z-50 flex w-full justify-between">
<span className="line-clamp-1 block">{x.name}</span>
<div className="space-x-2">
<span className="font-bold text-muted-foreground">
{toGibibytes(x.metadata.size)}
</span>
{x.engine == InferenceEngine.nitro &&
getLabel(x.metadata.size)}
</div>
</div> </div>
</div> </SelectItem>
</SelectItem> ))}
))} </SelectGroup>
</SelectGroup> )}
)} <div className="border-b border-border" />
<div className="border-b border-border" /> <div className="w-full px-4 py-2">
<div className="w-full px-4 py-2"> <Button
<Button block
block className="bg-blue-100 font-bold text-blue-600 hover:bg-blue-100 hover:text-blue-600"
className="bg-blue-100 font-bold text-blue-600 hover:bg-blue-100 hover:text-blue-600" onClick={() => setMainViewState(MainViewState.Hub)}
onClick={() => setMainViewState(MainViewState.Hub)} >
> Explore The Hub
Explore The Hub </Button>
</Button> </div>
</div> </SelectContent>
</SelectContent> </SelectPortal>
</Select> </Select>
<OpenAiKeyInput selectedModel={selectedModel} /> <OpenAiKeyInput selectedModel={selectedModel} />
</> </>
{selected?.engine === InferenceEngine.openai && (
<div className="mt-4">
<label
id="thread-title"
className="mb-2 inline-block font-bold text-gray-600 dark:text-gray-300"
>
API Key
</label>
<Input
id="assistant-instructions"
placeholder="Enter your API_KEY"
defaultValue={openAISettings?.api_key}
onChange={(e) => {
saveOpenAISettings({ apiKey: e.target.value })
}}
/>
</div>
)}
</div>
) )
} }

View File

@ -47,7 +47,7 @@ const Logs = () => {
r="55.9425" r="55.9425"
fill="#E7E7E7" fill="#E7E7E7"
stroke="white" stroke="white"
stroke-width="3.1151" strokeWidth="3.1151"
/> />
<mask <mask
id="mask0_1206_120508" id="mask0_1206_120508"
@ -146,8 +146,8 @@ const Logs = () => {
y2="114.947" y2="114.947"
gradientUnits="userSpaceOnUse" gradientUnits="userSpaceOnUse"
> >
<stop stop-color="#CFCFCF" /> <stop stopColor="#CFCFCF" />
<stop offset="1" stop-color="#C6C6C6" /> <stop offset="1" stopColor="#C6C6C6" />
</linearGradient> </linearGradient>
<linearGradient <linearGradient
id="paint1_linear_1206_120508" id="paint1_linear_1206_120508"
@ -157,8 +157,8 @@ const Logs = () => {
y2="88.9801" y2="88.9801"
gradientUnits="userSpaceOnUse" gradientUnits="userSpaceOnUse"
> >
<stop stop-color="#DDDDDD" /> <stop stopColor="#DDDDDD" />
<stop offset="1" stop-color="#B6B6B6" /> <stop offset="1" stopColor="#B6B6B6" />
</linearGradient> </linearGradient>
</defs> </defs>
</svg> </svg>

View File

@ -1,6 +1,6 @@
'use client' 'use client'
import React, { useState } from 'react' import React, { useEffect, useState } from 'react'
import { import {
Button, Button,
@ -70,6 +70,18 @@ const LocalServerScreen = () => {
const [host, setHost] = useAtom(hostAtom) const [host, setHost] = useAtom(hostAtom)
const [port, setPort] = useAtom(portAtom) const [port, setPort] = useAtom(portAtom)
const FIRST_TIME_VISIT_API_SERVER = 'firstTimeVisitAPIServer'
const [firstTimeVisitAPIServer, setFirstTimeVisitAPIServer] =
useState<boolean>(false)
useEffect(() => {
if (localStorage.getItem(FIRST_TIME_VISIT_API_SERVER) === null) {
localStorage.setItem(FIRST_TIME_VISIT_API_SERVER, 'true')
setFirstTimeVisitAPIServer(true)
}
}, [])
return ( return (
<div className="flex h-full w-full"> <div className="flex h-full w-full">
{/* Left SideBar */} {/* Left SideBar */}
@ -213,13 +225,13 @@ const LocalServerScreen = () => {
{/* Middle Bar */} {/* Middle Bar */}
<div className="relative flex h-full w-full flex-col overflow-auto bg-background"> <div 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"> <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">
<Button <Button
size="sm" size="sm"
themes="outline" themes="outline"
className="bg-white" className="bg-white dark:bg-secondary"
onClick={() => openServerLog()} onClick={() => openServerLog()}
> >
<CodeIcon size={16} className="mr-2" /> <CodeIcon size={16} className="mr-2" />
@ -228,7 +240,7 @@ const LocalServerScreen = () => {
<Button <Button
size="sm" size="sm"
themes="outline" themes="outline"
className="bg-white" className="bg-white dark:bg-secondary"
onClick={() => clearServerLog()} onClick={() => clearServerLog()}
> >
<Paintbrush size={16} className="mr-2" /> <Paintbrush size={16} className="mr-2" />
@ -236,7 +248,47 @@ const LocalServerScreen = () => {
</Button> </Button>
</div> </div>
</div> </div>
<Logs /> {firstTimeVisitAPIServer ? (
<div className="flex h-full items-center justify-center">
<div className="w-[335px] rounded-lg border border-blue-600 bg-blue-100 p-6">
<div className="item-start flex gap-x-4">
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
className="mt-1 flex-shrink-0"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M10 20C15.5228 20 20 15.5228 20 10C20 4.47715 15.5228 0 10 0C4.47715 0 2.11188e-08 4.47715 2.11188e-08 10C2.11188e-08 12.397 0.843343 14.597 2.2495 16.3195L0.292453 18.2929C-0.332289 18.9229 0.110179 20 0.993697 20H10ZM5.5 8C5.5 7.44772 5.94772 7 6.5 7H13.5C14.0523 7 14.5 7.44772 14.5 8C14.5 8.55229 14.0523 9 13.5 9H6.5C5.94772 9 5.5 8.55229 5.5 8ZM6.5 11C5.94772 11 5.5 11.4477 5.5 12C5.5 12.5523 5.94772 13 6.5 13H9.5C10.0523 13 10.5 12.5523 10.5 12C10.5 11.4477 10.0523 11 9.5 11H6.5Z"
fill="#2563EB"
/>
</svg>
<div>
<h6 className="font-medium text-black">
You cannot chat with your assistant while the server is
running.
</h6>
<Button
className="mt-4"
onClick={() => {
localStorage.setItem(FIRST_TIME_VISIT_API_SERVER, 'false')
setFirstTimeVisitAPIServer(false)
}}
>
Got it
</Button>
</div>
</div>
</div>
</div>
) : (
<Logs />
)}
</div> </div>
{/* Right bar */} {/* Right bar */}