mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-05-25 18:55:19 +02:00
move assistant selection to the top
This commit is contained in:
parent
9d54d971d2
commit
3fbc739a24
1 changed files with 117 additions and 12 deletions
|
|
@ -2,7 +2,7 @@
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import { Tooltip } from "@heroui/react";
|
import { Tooltip, Modal, ModalContent, ModalHeader, ModalBody, useDisclosure } from "@heroui/react";
|
||||||
import { UserButton } from "@/app/lib/components/user_button";
|
import { UserButton } from "@/app/lib/components/user_button";
|
||||||
import {
|
import {
|
||||||
SettingsIcon,
|
SettingsIcon,
|
||||||
|
|
@ -15,10 +15,12 @@ import {
|
||||||
Sun,
|
Sun,
|
||||||
HelpCircle
|
HelpCircle
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { getProjectConfig } from "@/app/actions/project_actions";
|
import { getProjectConfig, listProjects } from "@/app/actions/project_actions";
|
||||||
import { useTheme } from "@/app/providers/theme-provider";
|
import { useTheme } from "@/app/providers/theme-provider";
|
||||||
import { USE_PRODUCT_TOUR } from '@/app/lib/feature_flags';
|
import { USE_PRODUCT_TOUR } from '@/app/lib/feature_flags';
|
||||||
import { useHelpModal } from "@/app/providers/help-modal-provider";
|
import { useHelpModal } from "@/app/providers/help-modal-provider";
|
||||||
|
import { Project } from "@/app/lib/types/project_types";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
interface SidebarProps {
|
interface SidebarProps {
|
||||||
projectId?: string;
|
projectId?: string;
|
||||||
|
|
@ -34,9 +36,12 @@ const COLLAPSED_ICON_SIZE = 20; // DO NOT CHANGE THIS
|
||||||
export default function Sidebar({ projectId, useAuth, collapsed = false, onToggleCollapse, useBilling }: SidebarProps) {
|
export default function Sidebar({ projectId, useAuth, collapsed = false, onToggleCollapse, useBilling }: SidebarProps) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const [projectName, setProjectName] = useState<string>("Select Project");
|
const [projectName, setProjectName] = useState<string>("Select Project");
|
||||||
|
const [allProjects, setAllProjects] = useState<z.infer<typeof Project>[]>([]);
|
||||||
|
const [isLoadingProjects, setIsLoadingProjects] = useState(false);
|
||||||
const isProjectsRoute = pathname === '/projects';
|
const isProjectsRoute = pathname === '/projects';
|
||||||
const { theme, toggleTheme } = useTheme();
|
const { theme, toggleTheme } = useTheme();
|
||||||
const { showHelpModal } = useHelpModal();
|
const { showHelpModal } = useHelpModal();
|
||||||
|
const { isOpen: isAssistantsModalOpen, onOpen: onAssistantsModalOpen, onClose: onAssistantsModalClose } = useDisclosure();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchProjectName() {
|
async function fetchProjectName() {
|
||||||
|
|
@ -53,18 +58,36 @@ export default function Sidebar({ projectId, useAuth, collapsed = false, onToggl
|
||||||
fetchProjectName();
|
fetchProjectName();
|
||||||
}, [projectId, isProjectsRoute]);
|
}, [projectId, isProjectsRoute]);
|
||||||
|
|
||||||
|
// Load projects when modal opens
|
||||||
|
useEffect(() => {
|
||||||
|
async function loadProjects() {
|
||||||
|
if (isAssistantsModalOpen && !isProjectsRoute) {
|
||||||
|
setIsLoadingProjects(true);
|
||||||
|
try {
|
||||||
|
const projects = await listProjects();
|
||||||
|
// Filter out current project and sort by creation date
|
||||||
|
const otherProjects = projects.filter(p => p._id !== projectId);
|
||||||
|
const sortedProjects = [...otherProjects].sort((a, b) =>
|
||||||
|
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
|
||||||
|
);
|
||||||
|
setAllProjects(sortedProjects);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch projects:', error);
|
||||||
|
} finally {
|
||||||
|
setIsLoadingProjects(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadProjects();
|
||||||
|
}, [isAssistantsModalOpen, projectId, isProjectsRoute]);
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{
|
{
|
||||||
href: 'workflow',
|
href: 'workflow',
|
||||||
label: 'Build',
|
label: 'Build',
|
||||||
icon: WorkflowIcon,
|
icon: WorkflowIcon,
|
||||||
requiresProject: true
|
requiresProject: true
|
||||||
},
|
|
||||||
{
|
|
||||||
href: 'config',
|
|
||||||
label: 'Settings',
|
|
||||||
icon: SettingsIcon,
|
|
||||||
requiresProject: true
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -82,10 +105,10 @@ export default function Sidebar({ projectId, useAuth, collapsed = false, onToggl
|
||||||
{/* Project Selector */}
|
{/* Project Selector */}
|
||||||
<div className="p-3 border-b border-zinc-100 dark:border-zinc-800">
|
<div className="p-3 border-b border-zinc-100 dark:border-zinc-800">
|
||||||
<Tooltip content={collapsed ? projectName : "Change project"} showArrow placement="right">
|
<Tooltip content={collapsed ? projectName : "Change project"} showArrow placement="right">
|
||||||
<Link
|
<button
|
||||||
href="/projects"
|
onClick={onAssistantsModalOpen}
|
||||||
className={`
|
className={`
|
||||||
flex items-center rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-800/50 transition-all
|
w-full flex items-center rounded-md hover:bg-zinc-100 dark:hover:bg-zinc-800/50 transition-all
|
||||||
${collapsed ? 'justify-center py-4' : 'gap-3 px-4 py-2.5'}
|
${collapsed ? 'justify-center py-4' : 'gap-3 px-4 py-2.5'}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
|
|
@ -98,7 +121,7 @@ export default function Sidebar({ projectId, useAuth, collapsed = false, onToggl
|
||||||
{projectName}
|
{projectName}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</Link>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -175,6 +198,28 @@ export default function Sidebar({ projectId, useAuth, collapsed = false, onToggl
|
||||||
|
|
||||||
{/* Theme and Auth Controls */}
|
{/* Theme and Auth Controls */}
|
||||||
<div className="p-3 border-t border-zinc-100 dark:border-zinc-800 space-y-2">
|
<div className="p-3 border-t border-zinc-100 dark:border-zinc-800 space-y-2">
|
||||||
|
{/* Settings */}
|
||||||
|
{!isProjectsRoute && projectId && (
|
||||||
|
<Tooltip content={collapsed ? "Settings" : ""} showArrow placement="right">
|
||||||
|
<Link
|
||||||
|
href={`/projects/${projectId}/config`}
|
||||||
|
className={`
|
||||||
|
w-full rounded-md flex items-center
|
||||||
|
text-[15px] font-medium transition-all duration-200
|
||||||
|
${collapsed ? 'justify-center py-4' : 'px-4 py-4 gap-3'}
|
||||||
|
${pathname.startsWith(`/projects/${projectId}/config`)
|
||||||
|
? 'bg-indigo-50 dark:bg-indigo-500/10 text-indigo-600 dark:text-indigo-400'
|
||||||
|
: 'hover:bg-zinc-100 dark:hover:bg-zinc-800/50 text-zinc-600 dark:text-zinc-400'
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
data-tour-target="settings"
|
||||||
|
>
|
||||||
|
<SettingsIcon size={COLLAPSED_ICON_SIZE} />
|
||||||
|
{!collapsed && <span>Settings</span>}
|
||||||
|
</Link>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
{USE_PRODUCT_TOUR && !isProjectsRoute && (
|
{USE_PRODUCT_TOUR && !isProjectsRoute && (
|
||||||
<Tooltip content={collapsed ? "Help" : ""} showArrow placement="right">
|
<Tooltip content={collapsed ? "Help" : ""} showArrow placement="right">
|
||||||
<button
|
<button
|
||||||
|
|
@ -228,6 +273,66 @@ export default function Sidebar({ projectId, useAuth, collapsed = false, onToggl
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
|
{/* Assistants Modal */}
|
||||||
|
<Modal
|
||||||
|
isOpen={isAssistantsModalOpen}
|
||||||
|
onClose={onAssistantsModalClose}
|
||||||
|
size="2xl"
|
||||||
|
scrollBehavior="inside"
|
||||||
|
>
|
||||||
|
<ModalContent>
|
||||||
|
<ModalHeader className="flex flex-col gap-1">
|
||||||
|
Select Assistant
|
||||||
|
</ModalHeader>
|
||||||
|
<ModalBody>
|
||||||
|
<div className="space-y-2">
|
||||||
|
{/* Current project option */}
|
||||||
|
<Link
|
||||||
|
href="/projects"
|
||||||
|
onClick={onAssistantsModalClose}
|
||||||
|
className="block px-4 py-3 text-sm hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-md transition-colors border-2 border-indigo-200 dark:border-indigo-800 bg-indigo-50 dark:bg-indigo-950/30"
|
||||||
|
>
|
||||||
|
<div className="font-medium text-indigo-700 dark:text-indigo-300">Create New Assistant</div>
|
||||||
|
<div className="text-xs text-indigo-600 dark:text-indigo-400">
|
||||||
|
Start building a new assistant from scratch
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
{isLoadingProjects ? (
|
||||||
|
<div className="flex items-center justify-center py-8 text-sm text-zinc-500">
|
||||||
|
Loading assistants...
|
||||||
|
</div>
|
||||||
|
) : allProjects.length > 0 ? (
|
||||||
|
<>
|
||||||
|
<div className="text-sm font-medium text-zinc-700 dark:text-zinc-300 px-1 py-2">
|
||||||
|
Existing Assistants ({allProjects.length})
|
||||||
|
</div>
|
||||||
|
<div className="space-y-1 max-h-96 overflow-y-auto">
|
||||||
|
{allProjects.map((project) => (
|
||||||
|
<Link
|
||||||
|
key={project._id}
|
||||||
|
href={`/projects/${project._id}/workflow`}
|
||||||
|
onClick={onAssistantsModalClose}
|
||||||
|
className="block px-4 py-3 text-sm text-zinc-600 dark:text-zinc-400 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-md transition-colors"
|
||||||
|
>
|
||||||
|
<div className="font-medium text-zinc-900 dark:text-zinc-100">{project.name}</div>
|
||||||
|
<div className="text-xs text-zinc-500 dark:text-zinc-500">
|
||||||
|
Created {new Date(project.createdAt).toLocaleDateString()}
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div className="text-sm text-zinc-500 dark:text-zinc-500 text-center py-8">
|
||||||
|
No other assistants found
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ModalBody>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue