feat: change layout thread setting right panel

This commit is contained in:
Faisal Amir 2024-01-01 09:11:36 +07:00
parent ed3e3600aa
commit 2332c4e1d2
3 changed files with 228 additions and 65 deletions

View File

@ -39,15 +39,24 @@ export default function CardSidebar({
return ( return (
<div <div
className={twMerge( className={twMerge(
'flex w-full flex-col overflow-hidden rounded-md border border-border bg-zinc-200 dark:bg-zinc-600/10' 'flex w-full flex-col overflow-hidden border-t border-border bg-zinc-200 dark:bg-zinc-600/10'
)} )}
> >
<div <div
className={twMerge( className={twMerge(
'relative flex items-center rounded-t-md ', 'relative flex items-center justify-between pl-4',
show && 'border-b border-border' show && 'border-b border-border'
)} )}
> >
<span className="font-bold">{title}</span>
<div className="flex">
<div
ref={setToggle}
className="cursor-pointer rounded-md bg-zinc-200 p-2 pr-0 dark:bg-zinc-600/10"
onClick={() => setMore(!more)}
>
<MoreVerticalIcon className="h-5 w-5" />
</div>
<button <button
onClick={() => setShow(!show)} onClick={() => setShow(!show)}
className="flex w-full flex-1 items-center space-x-2 bg-zinc-200 px-3 py-2 dark:bg-zinc-600/10" className="flex w-full flex-1 items-center space-x-2 bg-zinc-200 px-3 py-2 dark:bg-zinc-600/10"
@ -58,15 +67,9 @@ export default function CardSidebar({
show && 'rotate-180' show && 'rotate-180'
)} )}
/> />
<span className="font-bold">{title}</span>
</button> </button>
<div
ref={setToggle}
className="cursor-pointer rounded-md bg-zinc-200 p-2 dark:bg-zinc-600/10"
onClick={() => setMore(!more)}
>
<MoreVerticalIcon className="h-5 w-5" />
</div> </div>
{more && ( {more && (
<div <div
className="absolute right-0 top-8 z-20 w-52 overflow-hidden rounded-lg border border-border bg-background shadow-lg" className="absolute right-0 top-8 z-20 w-52 overflow-hidden rounded-lg border border-border bg-background shadow-lg"

View File

@ -1,18 +1,31 @@
import { useState } from 'react'
import { getUserSpace, joinPath, openFileExplorer } from '@janhq/core'
import { useAtomValue, useSetAtom } from 'jotai' import { useAtomValue, useSetAtom } from 'jotai'
import { PanelLeftIcon, PenSquareIcon, PanelRightIcon } from 'lucide-react' import {
PanelLeftIcon,
PenSquareIcon,
PanelRightIcon,
MoreVerticalIcon,
FolderOpenIcon,
Code2Icon,
} from 'lucide-react'
import { twMerge } from 'tailwind-merge'
import CommandListDownloadedModel from '@/containers/Layout/TopBar/CommandListDownloadedModel' import CommandListDownloadedModel from '@/containers/Layout/TopBar/CommandListDownloadedModel'
import CommandSearch from '@/containers/Layout/TopBar/CommandSearch' import CommandSearch from '@/containers/Layout/TopBar/CommandSearch'
import { MainViewState } from '@/constants/screens' import { MainViewState } from '@/constants/screens'
import { useClickOutside } from '@/hooks/useClickOutside'
import { useCreateNewThread } from '@/hooks/useCreateNewThread' import { useCreateNewThread } from '@/hooks/useCreateNewThread'
import useGetAssistants, { getAssistants } from '@/hooks/useGetAssistants' import useGetAssistants, { getAssistants } from '@/hooks/useGetAssistants'
import { useMainViewState } from '@/hooks/useMainViewState' import { useMainViewState } from '@/hooks/useMainViewState'
import { showRightSideBarAtom } from '@/screens/Chat/Sidebar' import { showRightSideBarAtom } from '@/screens/Chat/Sidebar'
import { activeThreadAtom } from '@/helpers/atoms/Thread.atom' import { activeThreadAtom, threadStatesAtom } from '@/helpers/atoms/Thread.atom'
const TopBar = () => { const TopBar = () => {
const activeThread = useAtomValue(activeThreadAtom) const activeThread = useAtomValue(activeThreadAtom)
@ -20,6 +33,13 @@ const TopBar = () => {
const { requestCreateNewThread } = useCreateNewThread() const { requestCreateNewThread } = useCreateNewThread()
const { assistants } = useGetAssistants() const { assistants } = useGetAssistants()
const setShowRightSideBar = useSetAtom(showRightSideBarAtom) const setShowRightSideBar = useSetAtom(showRightSideBarAtom)
const showing = useAtomValue(showRightSideBarAtom)
const threadStates = useAtomValue(threadStatesAtom)
const [more, setMore] = useState(false)
const [menu, setMenu] = useState<HTMLDivElement | null>(null)
const [toggle, setToggle] = useState<HTMLDivElement | null>(null)
useClickOutside(() => setMore(false), null, [menu, toggle])
const titleScreen = (viewStateName: MainViewState) => { const titleScreen = (viewStateName: MainViewState) => {
switch (viewStateName) { switch (viewStateName) {
@ -47,15 +67,45 @@ const TopBar = () => {
} }
} }
const onReviewInFinderClick = async () => {
if (!activeThread) return
const activeThreadState = threadStates[activeThread.id]
if (!activeThreadState.isFinishInit) {
alert('Thread is not started yet')
return
}
const userSpace = await getUserSpace()
let filePath = undefined
filePath = await joinPath(['threads', activeThread.id])
if (!filePath) return
const fullPath = await joinPath([userSpace, filePath])
openFileExplorer(fullPath)
}
const onViewJsonClick = async () => {
if (!activeThread) return
const activeThreadState = threadStates[activeThread.id]
if (!activeThreadState.isFinishInit) {
alert('Thread is not started yet')
return
}
const userSpace = await getUserSpace()
let filePath = undefined
filePath = await joinPath(['threads', activeThread.id, 'thread.json'])
if (!filePath) return
const fullPath = await joinPath([userSpace, filePath])
openFileExplorer(fullPath)
}
return ( return (
<div className="fixed left-0 top-0 z-50 flex h-12 w-full border-b border-border bg-background/80 backdrop-blur-md"> <div className="fixed left-0 top-0 z-50 flex h-12 w-full border-b border-border bg-background/80 backdrop-blur-md">
{mainViewState === MainViewState.Thread && ( {mainViewState === MainViewState.Thread && (
<div className="absolute left-16 h-full w-60 border-r border-border" /> <div className="relative w-full">
)} <div className="absolute left-16 h-full w-60 border-r border-border">
<div className="relative left-16 flex w-[calc(100%-64px)] items-center justify-between space-x-4 pl-6 pr-2"> <div className="flex h-full w-full items-center justify-between">
{mainViewState === MainViewState.Thread ? (
<div className="unset-drag flex space-x-8">
<div className="flex w-52 justify-between">
<div className="cursor-pointer"> <div className="cursor-pointer">
<PanelLeftIcon <PanelLeftIcon
size={20} size={20}
@ -63,26 +113,100 @@ const TopBar = () => {
/> />
</div> </div>
<div <div
className="cursor-pointer pr-2" className="unset-drag cursor-pointer pr-4"
onClick={onCreateConversationClick} onClick={onCreateConversationClick}
> >
<PenSquareIcon size={20} className="text-muted-foreground" /> <PenSquareIcon size={20} className="text-muted-foreground" />
</div> </div>
</div> </div>
</div>
<div className="absolute left-80 h-full">
<div className="flex h-full items-center">
<span className="text-sm font-bold"> <span className="text-sm font-bold">
{titleScreen(mainViewState)} {titleScreen(mainViewState)}
</span> </span>
</div>
</div>
<div
className={twMerge(
'absolute right-0 h-full w-80',
showing && 'border-l border-border'
)}
>
{activeThread && ( {activeThread && (
<div className="flex h-full w-52 items-center justify-between px-4">
{showing && (
<div className="relative flex h-full items-center">
<span className="mr-2 text-sm font-bold">
Threads Settings
</span>
<div
ref={setToggle}
className="unset-drag cursor-pointer rounded-md p-2"
onClick={() => setMore(!more)}
>
<MoreVerticalIcon className="h-5 w-5" />
</div>
{more && (
<div
className="absolute right-0 top-11 z-20 w-64 overflow-hidden rounded-lg border border-border bg-background shadow-lg"
ref={setMenu}
>
<div
className="flex cursor-pointer items-center space-x-2 px-4 py-2 hover:bg-secondary"
onClick={() => {
onReviewInFinderClick()
setMore(false)
}}
>
<FolderOpenIcon
size={16}
className="text-muted-foreground"
/>
<span className="font-medium text-black dark:text-muted-foreground">
Show in Finder
</span>
</div>
<div
className="flex cursor-pointer items-start space-x-2 px-4 py-2 hover:bg-secondary"
onClick={() => {
onViewJsonClick()
setMore(false)
}}
>
<Code2Icon
size={16}
className="mt-1 flex-shrink-0 text-muted-foreground"
/>
<div className="flex flex-col">
<span className="font-medium text-black dark:text-muted-foreground">
View as JSON
</span>
<span className="mt-1 text-muted-foreground">
Opens thread.json. Changes affect this thread
only.
</span>
</div>
</div>
</div>
)}
</div>
)}
<div <div
className="unset-drag absolute right-4 cursor-pointer" className="unset-drag absolute right-4 cursor-pointer"
onClick={() => setShowRightSideBar((show) => !show)} onClick={() => setShowRightSideBar((show) => !show)}
> >
<PanelRightIcon size={20} className="text-muted-foreground" /> <PanelRightIcon size={20} className="text-muted-foreground" />
</div> </div>
</div>
)} )}
</div> </div>
) : ( </div>
<div> )}
{mainViewState !== MainViewState.Thread && (
<div className="relative left-16 flex w-[calc(100%-64px)] items-center justify-between space-x-4 pl-6 pr-2">
<span className="text-sm font-bold"> <span className="text-sm font-bold">
{titleScreen(mainViewState)} {titleScreen(mainViewState)}
</span> </span>
@ -91,7 +215,6 @@ const TopBar = () => {
<CommandSearch /> <CommandSearch />
<CommandListDownloadedModel /> <CommandListDownloadedModel />
</div> </div>
</div>
) )
} }

View File

@ -119,11 +119,44 @@ const Sidebar: React.FC = () => {
> >
<div <div
className={twMerge( className={twMerge(
'flex flex-col gap-4 p-4 delay-200', 'flex flex-col gap-1 delay-200',
showing ? 'animate-enter opacity-100' : 'opacity-0' showing ? 'animate-enter opacity-100' : 'opacity-0'
)} )}
> >
<CardSidebar <div className="flex flex-col space-y-4 p-4">
<div>
<label
id="thread-title"
className="mb-2 inline-block font-bold text-gray-600 dark:text-gray-300"
>
Title
</label>
<Input
id="thread-title"
value={activeThread?.title}
onChange={(e) => {
if (activeThread)
updateThreadMetadata({
...activeThread,
title: e.target.value || '',
})
}}
/>
</div>
<div className="flex flex-col">
<label
id="thread-title"
className="mb-2 inline-block font-bold text-gray-600 dark:text-gray-300"
>
Threads ID
</label>
<span className="text-xs text-muted-foreground">
{activeThread?.id || '-'}
</span>
</div>
</div>
{/* <CardSidebar
title="Thread" title="Thread"
onRevealInFinderClick={onReviewInFinderClick} onRevealInFinderClick={onReviewInFinderClick}
onViewJsonClick={onViewJsonClick} onViewJsonClick={onViewJsonClick}
@ -160,8 +193,9 @@ const Sidebar: React.FC = () => {
</span> </span>
</div> </div>
</div> </div>
</CardSidebar> </CardSidebar> */}
<CardSidebar
{/* <CardSidebar
title="Assistant" title="Assistant"
onRevealInFinderClick={onReviewInFinderClick} onRevealInFinderClick={onReviewInFinderClick}
onViewJsonClick={onViewJsonClick} onViewJsonClick={onViewJsonClick}
@ -199,8 +233,21 @@ const Sidebar: React.FC = () => {
/> />
</div> </div>
</div> </div>
</CardSidebar> </CardSidebar> */}
{experimentalFeatureEnabed && Object.keys(modelSettingParams).length ? (
{/* <CardSidebar
title="Model"
onRevealInFinderClick={onReviewInFinderClick}
onViewJsonClick={onViewJsonClick}
>
<div className="p-2">
<DropdownListSidebar />
<div className="mt-4">
<ModelSetting />
</div>
{experimentalFeatureEnabed &&
Object.keys(modelSettingParams).length ? (
<CardSidebar <CardSidebar
title="Engine" title="Engine"
onRevealInFinderClick={onReviewInFinderClick} onRevealInFinderClick={onReviewInFinderClick}
@ -211,18 +258,8 @@ const Sidebar: React.FC = () => {
</div> </div>
</CardSidebar> </CardSidebar>
) : null} ) : null}
<CardSidebar
title="Model"
onRevealInFinderClick={onReviewInFinderClick}
onViewJsonClick={onViewJsonClick}
>
<div className="p-2">
<DropdownListSidebar />
<div className="mt-4">
<ModelSetting />
</div> </div>
</div> </CardSidebar> */}
</CardSidebar>
</div> </div>
</div> </div>
) )