mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-05-31 04:56:02 +00:00
feat(app): update workspace shell, nav, and integrations
Refresh IntegrationList, session rows, TopBar, and recent sessions. Remove recent-session delete from Workspace in favor of handling elsewhere. Made-with: Cursor
This commit is contained in:
parent
49f3b16c6d
commit
3f840fff88
5 changed files with 146 additions and 136 deletions
|
|
@ -14,10 +14,10 @@
|
|||
|
||||
import { fetchGet, fetchPost } from '@/api/http';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipSimple,
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui/tooltip';
|
||||
import { CircleAlert, Settings2 } from 'lucide-react';
|
||||
|
|
@ -36,6 +36,7 @@ import {
|
|||
} from '@/hooks/useIntegrationManagement';
|
||||
import { getProxyBaseURL } from '@/lib';
|
||||
import { OAuth } from '@/lib/oauth';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { MCPEnvDialog } from '@/pages/Connectors/components/MCPEnvDialog';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
|
@ -65,6 +66,11 @@ interface IntegrationListProps {
|
|||
installedKeys?: string[];
|
||||
oauth?: OAuth | null;
|
||||
translationNamespace?: 'layout' | 'setting'; // For translation keys
|
||||
className?: string;
|
||||
/** Select mode: show a leading checkbox; use isIntegrationSelected + onToggleIntegration */
|
||||
selectWithCheckbox?: boolean;
|
||||
isIntegrationSelected?: (item: IntegrationItem) => boolean;
|
||||
onToggleIntegration?: (item: IntegrationItem, selected: boolean) => void;
|
||||
}
|
||||
|
||||
export default function IntegrationList({
|
||||
|
|
@ -84,6 +90,10 @@ export default function IntegrationList({
|
|||
installedKeys: _installedKeys = [],
|
||||
oauth: _oauth,
|
||||
translationNamespace = variant === 'select' ? 'layout' : 'setting',
|
||||
className: rootClassName,
|
||||
selectWithCheckbox = false,
|
||||
isIntegrationSelected,
|
||||
onToggleIntegration,
|
||||
}: IntegrationListProps) {
|
||||
const { t } = useTranslation();
|
||||
const [showEnvConfig, setShowEnvConfig] = useState(false);
|
||||
|
|
@ -294,15 +304,15 @@ export default function IntegrationList({
|
|||
: 'flex flex-col w-full items-start justify-start gap-4';
|
||||
|
||||
const itemClassName = isSelectMode
|
||||
? 'cursor-pointer hover:bg-ds-bg-neutral-default-hover px-3 py-2 flex justify-between'
|
||||
? 'cursor-pointer gap-2 rounded-lg bg-ds-bg-neutral-subtle-default px-3 py-2 min-h-0 flex w-full items-center justify-between hover:bg-ds-bg-neutral-default-hover'
|
||||
: 'w-full px-6 py-4 bg-ds-bg-neutral-subtle-default rounded-2xl';
|
||||
|
||||
const titleClassName = isSelectMode
|
||||
? 'text-base leading-snug font-bold text-ds-text-brand-default-default'
|
||||
? 'min-w-0 flex-1 text-sm font-bold leading-5 text-ds-text-neutral-default-default sm:text-base line-clamp-2 break-words'
|
||||
: 'text-label-lg font-bold text-ds-text-neutral-default-default';
|
||||
|
||||
return (
|
||||
<div className={containerClassName}>
|
||||
<div className={cn(containerClassName, rootClassName)}>
|
||||
<MCPEnvDialog
|
||||
showEnvConfig={showEnvConfig}
|
||||
onClose={onClose}
|
||||
|
|
@ -312,6 +322,12 @@ export default function IntegrationList({
|
|||
{sortedItems.map((item) => {
|
||||
const isInstalled = !!installed[item.key];
|
||||
const isComingSoon = COMING_SOON_ITEMS.includes(item.name);
|
||||
const envCount = item.env_vars?.length ?? 0;
|
||||
const selectedForTool =
|
||||
selectWithCheckbox && isIntegrationSelected
|
||||
? isIntegrationSelected(item)
|
||||
: false;
|
||||
const checkboxDisabled = isComingSoon || (!isInstalled && envCount > 0);
|
||||
|
||||
return (
|
||||
<div key={item.key} className="w-full">
|
||||
|
|
@ -320,45 +336,48 @@ export default function IntegrationList({
|
|||
onClick={
|
||||
isSelectMode
|
||||
? () => {
|
||||
if (!isComingSoon) {
|
||||
if (item.env_vars.length === 0 || isInstalled) {
|
||||
// Ensure toolkit field is passed and normalized for known cases
|
||||
const normalizedToolkit =
|
||||
item.name === 'Notion'
|
||||
? 'notion_mcp_toolkit'
|
||||
: item.toolkit;
|
||||
addOption?.(
|
||||
{ ...item, toolkit: normalizedToolkit },
|
||||
true
|
||||
);
|
||||
if (isComingSoon) return;
|
||||
if (selectWithCheckbox && onToggleIntegration) {
|
||||
if (isInstalled) {
|
||||
onToggleIntegration(item, !selectedForTool);
|
||||
} else if (envCount === 0) {
|
||||
onToggleIntegration(item, !selectedForTool);
|
||||
} else {
|
||||
handleInstall(item);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (envCount === 0 || isInstalled) {
|
||||
const normalizedToolkit =
|
||||
item.name === 'Notion'
|
||||
? 'notion_mcp_toolkit'
|
||||
: item.toolkit;
|
||||
addOption?.(
|
||||
{ ...item, toolkit: normalizedToolkit },
|
||||
true
|
||||
);
|
||||
} else {
|
||||
handleInstall(item);
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{isSelectMode ? (
|
||||
<div className="gap-xs flex items-center">
|
||||
{(isSelectMode || showStatusDot) && (
|
||||
<img
|
||||
src={ellipseIcon}
|
||||
alt="icon"
|
||||
className="mr-2 h-3 w-3"
|
||||
style={{
|
||||
filter: isInstalled
|
||||
? 'grayscale(0%) brightness(0) saturate(100%) invert(41%) sepia(99%) saturate(749%) hue-rotate(81deg) brightness(95%) contrast(92%)'
|
||||
: 'none',
|
||||
<div className="gap-2 min-w-0 min-h-0 flex flex-1 items-center">
|
||||
{selectWithCheckbox && (
|
||||
<Checkbox
|
||||
disabled={checkboxDisabled}
|
||||
checked={selectedForTool}
|
||||
onCheckedChange={(c) => {
|
||||
if (c === 'indeterminate') return;
|
||||
onToggleIntegration?.(item, c === true);
|
||||
}}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
aria-label={item.name}
|
||||
/>
|
||||
)}
|
||||
<div className={titleClassName}>{item.name}</div>
|
||||
<div className="flex items-center">
|
||||
<TooltipSimple content={item.desc}>
|
||||
<CircleAlert className="h-4 w-4 text-ds-icon-neutral-muted-default" />
|
||||
</TooltipSimple>
|
||||
</div>
|
||||
<span className={titleClassName}>{item.name}</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="gap-xs flex w-full flex-row items-center justify-between">
|
||||
|
|
@ -433,7 +452,7 @@ export default function IntegrationList({
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
{isSelectMode && item.env_vars.length !== 0 && (
|
||||
{isSelectMode && envCount !== 0 && (
|
||||
<Button
|
||||
disabled={isComingSoon}
|
||||
variant={isInstalled ? 'secondary' : 'primary'}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ export interface NavListSessionRowsProps {
|
|||
* neutral hover fill; sidebar keeps the subtle fill.
|
||||
*/
|
||||
panelListHover?: boolean;
|
||||
/** When false, hide the trailing ⋯ row menu (workspace recent: time only). */
|
||||
showRowMenu?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -65,6 +67,7 @@ export function NavListSessionRows({
|
|||
folded,
|
||||
maxItems,
|
||||
panelListHover = false,
|
||||
showRowMenu = true,
|
||||
}: NavListSessionRowsProps) {
|
||||
const { t } = useTranslation();
|
||||
const deleteLabel = t('layout.sessions-delete-session', {
|
||||
|
|
@ -115,7 +118,8 @@ export function NavListSessionRows({
|
|||
<div key={session.id} className="min-w-0">
|
||||
<div
|
||||
className={cn(
|
||||
'group/session-item min-w-0 h-8 gap-1 rounded-xl pl-3 pr-1 relative flex w-full items-center overflow-hidden',
|
||||
'group/session-item min-w-0 h-8 gap-1 rounded-xl pl-3 relative flex w-full items-center overflow-hidden',
|
||||
showRowMenu ? 'pr-1' : 'pr-3',
|
||||
'transition-colors duration-150',
|
||||
active
|
||||
? panelListHover
|
||||
|
|
@ -148,58 +152,62 @@ export function NavListSessionRows({
|
|||
) : null}
|
||||
</button>
|
||||
|
||||
<span
|
||||
className={cn(
|
||||
'top-0 bottom-0 right-7 w-14 pointer-events-none absolute z-[1] bg-gradient-to-l to-transparent',
|
||||
active
|
||||
? panelListHover
|
||||
? 'from-ds-bg-neutral-muted-default group-hover/session-item:from-ds-bg-neutral-default-default'
|
||||
: 'from-ds-bg-neutral-subtle-default'
|
||||
: [
|
||||
'from-transparent',
|
||||
panelListHover
|
||||
? 'group-hover/session-item:from-ds-bg-neutral-default-default'
|
||||
: 'group-hover/session-item:from-ds-bg-neutral-subtle-default',
|
||||
]
|
||||
)}
|
||||
aria-hidden
|
||||
/>
|
||||
{showRowMenu ? (
|
||||
<>
|
||||
<span
|
||||
className={cn(
|
||||
'top-0 bottom-0 right-7 w-14 pointer-events-none absolute z-[1] bg-gradient-to-l to-transparent',
|
||||
active
|
||||
? panelListHover
|
||||
? 'from-ds-bg-neutral-muted-default group-hover/session-item:from-ds-bg-neutral-default-default'
|
||||
: 'from-ds-bg-neutral-subtle-default'
|
||||
: [
|
||||
'from-transparent',
|
||||
panelListHover
|
||||
? 'group-hover/session-item:from-ds-bg-neutral-default-default'
|
||||
: 'group-hover/session-item:from-ds-bg-neutral-subtle-default',
|
||||
]
|
||||
)}
|
||||
aria-hidden
|
||||
/>
|
||||
|
||||
<div className="relative z-[2] shrink-0">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
'no-drag h-7 w-7 rounded-lg text-ds-icon-neutral-muted-default flex shrink-0 items-center justify-center transition-opacity duration-150 outline-none',
|
||||
active
|
||||
? panelListHover
|
||||
? 'bg-transparent opacity-100'
|
||||
: 'bg-ds-bg-neutral-subtle-default hover:bg-ds-bg-neutral-subtle-default opacity-100'
|
||||
: [
|
||||
'md:opacity-0 bg-transparent opacity-100',
|
||||
'md:group-hover/session-item:opacity-100',
|
||||
'md:group-focus-within/session-item:opacity-100',
|
||||
'data-[state=open]:opacity-100',
|
||||
],
|
||||
'focus-visible:ring-ds-ring-neutral-subtle-default focus-visible:ring-2 focus-visible:outline-none'
|
||||
)}
|
||||
aria-label={sessionMenuAria}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" aria-hidden />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="min-w-[9rem]">
|
||||
<DropdownMenuItem
|
||||
className="text-ds-text-error-default-default focus:text-ds-text-error-default-default cursor-pointer"
|
||||
onClick={() => onDeleteSession?.(session.id)}
|
||||
>
|
||||
{deleteLabel}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
<div className="relative z-[2] shrink-0">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
'no-drag h-7 w-7 rounded-lg text-ds-icon-neutral-muted-default flex shrink-0 items-center justify-center transition-opacity duration-150 outline-none',
|
||||
active
|
||||
? panelListHover
|
||||
? 'bg-transparent opacity-100'
|
||||
: 'bg-ds-bg-neutral-subtle-default hover:bg-ds-bg-neutral-subtle-default opacity-100'
|
||||
: [
|
||||
'md:opacity-0 bg-transparent opacity-100',
|
||||
'md:group-hover/session-item:opacity-100',
|
||||
'md:group-focus-within/session-item:opacity-100',
|
||||
'data-[state=open]:opacity-100',
|
||||
],
|
||||
'focus-visible:ring-ds-ring-neutral-subtle-default focus-visible:ring-2 focus-visible:outline-none'
|
||||
)}
|
||||
aria-label={sessionMenuAria}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<MoreHorizontal className="h-4 w-4" aria-hidden />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="min-w-[9rem]">
|
||||
<DropdownMenuItem
|
||||
className="text-ds-text-error-default-default focus:text-ds-text-error-default-default cursor-pointer"
|
||||
onClick={() => onDeleteSession?.(session.id)}
|
||||
>
|
||||
{deleteLabel}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ function HeaderWin() {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`drag left-0 right-0 top-0 !h-9 py-1 absolute z-50 flex items-center justify-between ${
|
||||
className={`drag left-0 right-0 top-0 !h-10 py-1 absolute z-50 flex items-center justify-between ${
|
||||
platform === 'darwin' ? 'pr-[2px] pl-[68px]' : 'pl-2'
|
||||
}`}
|
||||
id="titlebar"
|
||||
|
|
@ -195,14 +195,14 @@ function HeaderWin() {
|
|||
src={appearance === 'dark' ? eigentAppIconWhite : eigentAppIconBlack}
|
||||
alt="Eigent"
|
||||
className="h-6 w-6 mt-[2px] select-none"
|
||||
width={12}
|
||||
height={12}
|
||||
width={16}
|
||||
height={16}
|
||||
draggable={false}
|
||||
/>
|
||||
</div>
|
||||
<div className="drag min-w-0 flex h-full flex-1 items-center justify-between">
|
||||
<div className="relative z-50 flex h-full items-center">
|
||||
<div className="no-drag gap-2 pl-2 flex items-center">
|
||||
<div className="no-drag gap-2 pl-1 flex items-center">
|
||||
<div className="flex items-center">
|
||||
{isHistoryRoute ? (
|
||||
<TooltipSimple
|
||||
|
|
@ -212,16 +212,14 @@ function HeaderWin() {
|
|||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
size="sm"
|
||||
buttonContent="icon-only"
|
||||
className="no-drag rounded-full"
|
||||
onClick={() => navigate('/')}
|
||||
aria-label={t('layout.projects')}
|
||||
aria-current="page"
|
||||
>
|
||||
<FolderOpen
|
||||
className="h-4 w-4 text-ds-icon-neutral-default-default"
|
||||
aria-hidden
|
||||
/>
|
||||
<FolderOpen aria-hidden />
|
||||
</Button>
|
||||
</TooltipSimple>
|
||||
) : (
|
||||
|
|
@ -232,16 +230,14 @@ function HeaderWin() {
|
|||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
size="sm"
|
||||
buttonContent="icon-only"
|
||||
className="no-drag rounded-full"
|
||||
onClick={() => navigate('/history')}
|
||||
aria-label={t('layout.dashboard')}
|
||||
aria-current="page"
|
||||
>
|
||||
<House
|
||||
className="h-4 w-4 text-ds-icon-neutral-default-default"
|
||||
aria-hidden
|
||||
/>
|
||||
<House aria-hidden />
|
||||
</Button>
|
||||
</TooltipSimple>
|
||||
)}
|
||||
|
|
@ -252,16 +248,14 @@ function HeaderWin() {
|
|||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
size="sm"
|
||||
buttonContent="icon-only"
|
||||
className="no-drag rounded-full"
|
||||
disabled={!canGoBack}
|
||||
onClick={() => navigate(-1)}
|
||||
aria-label={t('layout.back')}
|
||||
>
|
||||
<ChevronLeft
|
||||
className="h-4 w-4 text-ds-icon-neutral-default-default"
|
||||
aria-hidden
|
||||
/>
|
||||
<ChevronLeft aria-hidden />
|
||||
</Button>
|
||||
</TooltipSimple>
|
||||
<TooltipSimple
|
||||
|
|
@ -271,16 +265,14 @@ function HeaderWin() {
|
|||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
size="sm"
|
||||
buttonContent="icon-only"
|
||||
className="no-drag rounded-full"
|
||||
disabled={!canGoForward}
|
||||
onClick={() => navigate(1)}
|
||||
aria-label={t('layout.forward')}
|
||||
>
|
||||
<ChevronRight
|
||||
className="h-4 w-4 text-ds-icon-neutral-default-default"
|
||||
aria-hidden
|
||||
/>
|
||||
<ChevronRight aria-hidden />
|
||||
</Button>
|
||||
</TooltipSimple>
|
||||
</div>
|
||||
|
|
@ -335,9 +327,11 @@ function HeaderWin() {
|
|||
onClick={() =>
|
||||
handleShare(chatStore.activeTaskId as string)
|
||||
}
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="no-drag bg-ds-bg-information-subtle-default !text-ds-text-information-strong-default rounded-full"
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
buttonContent="icon-only"
|
||||
buttonRadius="full"
|
||||
tone="information"
|
||||
aria-label={t('layout.share')}
|
||||
>
|
||||
<Share aria-hidden />
|
||||
|
|
@ -352,14 +346,15 @@ function HeaderWin() {
|
|||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
size="sm"
|
||||
className="no-drag rounded-full"
|
||||
aria-label={t('layout.notifications')}
|
||||
aria-expanded={notificationPanelOpen}
|
||||
aria-controls="notification-panel"
|
||||
onClick={() => setNotificationPanelOpen((open) => !open)}
|
||||
buttonContent="icon-only"
|
||||
>
|
||||
<Bell className="h-4 w-4" aria-hidden />
|
||||
<Bell aria-hidden />
|
||||
</Button>
|
||||
</TooltipSimple>
|
||||
<TooltipSimple
|
||||
|
|
@ -370,12 +365,13 @@ function HeaderWin() {
|
|||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
size="sm"
|
||||
className="no-drag rounded-full"
|
||||
aria-label={t('layout.support')}
|
||||
onClick={() => setReportBugOpen(true)}
|
||||
buttonContent="icon-only"
|
||||
>
|
||||
<CircleHelp className="h-4 w-4" aria-hidden />
|
||||
<CircleHelp aria-hidden />
|
||||
</Button>
|
||||
</TooltipSimple>
|
||||
<TooltipSimple
|
||||
|
|
@ -386,13 +382,15 @@ function HeaderWin() {
|
|||
<Button
|
||||
onClick={getReferFriendsLink}
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
size="sm"
|
||||
className="no-drag rounded-full"
|
||||
buttonContent="icon-only"
|
||||
>
|
||||
<img
|
||||
src={appearance === 'dark' ? giftWhiteIcon : giftIcon}
|
||||
alt="gift-icon"
|
||||
className="h-4 w-4"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
</Button>
|
||||
</TooltipSimple>
|
||||
|
|
@ -404,10 +402,11 @@ function HeaderWin() {
|
|||
<Button
|
||||
onClick={() => navigate('/history?tab=settings')}
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
buttonContent="icon-only"
|
||||
size="sm"
|
||||
className="no-drag rounded-full"
|
||||
>
|
||||
<Settings className="h-4 w-4" />
|
||||
<Settings aria-hidden />
|
||||
</Button>
|
||||
</TooltipSimple>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ export interface WorkspaceRecentSessionsProps {
|
|||
activeTaskId: string | null;
|
||||
onSelectSession: (sessionId: string) => void;
|
||||
onOpenAllSessions: () => void;
|
||||
onDeleteSession: (sessionId: string) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -74,7 +73,6 @@ export function WorkspaceRecentSessions({
|
|||
activeTaskId,
|
||||
onSelectSession,
|
||||
onOpenAllSessions,
|
||||
onDeleteSession,
|
||||
}: WorkspaceRecentSessionsProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
|
@ -135,10 +133,10 @@ export function WorkspaceRecentSessions({
|
|||
sessions={sessions}
|
||||
activeSessionId={activeTaskId}
|
||||
onSessionClick={onSelectSession}
|
||||
onDeleteSession={onDeleteSession}
|
||||
folded={false}
|
||||
maxItems={NAV_LIST_SESSIONS_RECENT_MAX}
|
||||
panelListHover
|
||||
showRowMenu={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -87,19 +87,6 @@ export default function Workspace() {
|
|||
useState(false);
|
||||
const textareaRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const handleWorkspaceRecentDeleteSession = useCallback(
|
||||
(sessionId: string) => {
|
||||
if (!chatStore) return;
|
||||
if (!window.confirm(t('layout.delete-task-confirmation'))) return;
|
||||
const wasActive = chatStore.activeTaskId === sessionId;
|
||||
chatStore.removeTask(sessionId);
|
||||
if (wasActive) {
|
||||
setActiveWorkspaceTab('workforce');
|
||||
}
|
||||
},
|
||||
[chatStore, setActiveWorkspaceTab, t]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!workspaceWorkWithPanelOpen) return;
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
|
|
@ -427,7 +414,6 @@ export default function Workspace() {
|
|||
setActiveWorkspaceTab('session');
|
||||
}}
|
||||
onOpenAllSessions={() => setActiveWorkspaceTab('sessions')}
|
||||
onDeleteSession={handleWorkspaceRecentDeleteSession}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue