mirror of
https://github.com/aaif-goose/goose.git
synced 2026-07-03 14:10:03 +02:00
fix: display all project directories in sidebar and toolbar (#96)
The ProjectOption type used a singular workingDir that only captured the first directory. Switch to workingDirs array so every directory added in the project dialog is shown in the context panel, toolbar tooltip, and project selector dropdown. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -28,7 +28,7 @@ export interface ModelOption {
|
||||
export interface ProjectOption {
|
||||
id: string;
|
||||
name: string;
|
||||
workingDir?: string | null;
|
||||
workingDirs: string[];
|
||||
color?: string | null;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,9 @@ export function ChatInputToolbar({
|
||||
(project) => project.id === selectedProjectId,
|
||||
);
|
||||
const projectLabel = selectedProject?.name ?? "No project";
|
||||
const projectTitle = selectedProject?.workingDir ?? undefined;
|
||||
const projectTitle = selectedProject?.workingDirs.length
|
||||
? selectedProject.workingDirs.join(", ")
|
||||
: undefined;
|
||||
const providerLabel =
|
||||
availableProviderItems.find((provider) => provider.id === selectedProvider)
|
||||
?.label ?? formatProviderLabel(selectedProvider);
|
||||
@@ -219,7 +221,9 @@ export function ChatInputToolbar({
|
||||
...availableProjects.map((project) => ({
|
||||
value: project.id,
|
||||
label: project.name,
|
||||
description: project.workingDir ?? undefined,
|
||||
description: project.workingDirs.length
|
||||
? project.workingDirs.join(", ")
|
||||
: undefined,
|
||||
icon: <ProjectDot color={project.color} />,
|
||||
})),
|
||||
],
|
||||
|
||||
@@ -112,7 +112,7 @@ export function ChatView({
|
||||
.map((projectInfo) => ({
|
||||
id: projectInfo.id,
|
||||
name: projectInfo.name,
|
||||
workingDir: projectInfo.workingDirs[0] ?? null,
|
||||
workingDirs: projectInfo.workingDirs,
|
||||
color: projectInfo.color,
|
||||
})),
|
||||
[projects],
|
||||
@@ -451,7 +451,7 @@ export function ChatView({
|
||||
<ContextPanel
|
||||
projectName={project?.name}
|
||||
projectColor={project?.color}
|
||||
projectWorkingDir={project?.workingDirs[0] ?? null}
|
||||
projectWorkingDirs={project?.workingDirs ?? []}
|
||||
/>
|
||||
</aside>
|
||||
</motion.div>
|
||||
|
||||
@@ -17,7 +17,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/shared/ui/tabs";
|
||||
interface ContextPanelProps {
|
||||
projectName?: string;
|
||||
projectColor?: string;
|
||||
projectWorkingDir?: string | null;
|
||||
projectWorkingDirs?: string[];
|
||||
}
|
||||
|
||||
type ContextPanelTab = "details" | "files";
|
||||
@@ -52,16 +52,17 @@ function Widget({
|
||||
export function ContextPanel({
|
||||
projectName,
|
||||
projectColor,
|
||||
projectWorkingDir,
|
||||
projectWorkingDirs = [],
|
||||
}: ContextPanelProps) {
|
||||
const [activeTab, setActiveTab] = useState<ContextPanelTab>("details");
|
||||
const primaryWorkingDir = projectWorkingDirs[0] ?? null;
|
||||
const {
|
||||
data: gitState,
|
||||
error,
|
||||
isLoading,
|
||||
isFetching,
|
||||
refetch,
|
||||
} = useGitState(projectWorkingDir, activeTab === "details");
|
||||
} = useGitState(primaryWorkingDir, activeTab === "details");
|
||||
|
||||
const gitErrorMessage =
|
||||
error instanceof Error ? error.message : "Unable to read git status.";
|
||||
@@ -94,7 +95,7 @@ export function ContextPanel({
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
onClick={() => void refetch()}
|
||||
disabled={!projectWorkingDir || isFetching}
|
||||
disabled={!primaryWorkingDir || isFetching}
|
||||
className="rounded-md"
|
||||
aria-label="Refresh git status"
|
||||
title="Refresh git status"
|
||||
@@ -125,11 +126,17 @@ export function ContextPanel({
|
||||
) : (
|
||||
<p className="text-foreground-subtle">No project assigned.</p>
|
||||
)}
|
||||
<p className="truncate">
|
||||
{projectWorkingDir ?? "Folder not set"}
|
||||
</p>
|
||||
{projectWorkingDirs.length > 0 ? (
|
||||
projectWorkingDirs.map((dir) => (
|
||||
<p key={dir} className="truncate">
|
||||
{dir}
|
||||
</p>
|
||||
))
|
||||
) : (
|
||||
<p className="truncate">Folder not set</p>
|
||||
)}
|
||||
|
||||
{!projectWorkingDir ? null : isLoading && !gitState ? (
|
||||
{!primaryWorkingDir ? null : isLoading && !gitState ? (
|
||||
<div className="flex items-center gap-2 text-foreground">
|
||||
<Spinner className="size-3.5" />
|
||||
<span>Loading git status…</span>
|
||||
|
||||
@@ -143,7 +143,7 @@ describe("ChatInput", () => {
|
||||
{
|
||||
id: "project-1",
|
||||
name: "goose2",
|
||||
workingDir: "/Users/wesb/dev/goose2",
|
||||
workingDirs: ["/Users/wesb/dev/goose2"],
|
||||
},
|
||||
]}
|
||||
/>,
|
||||
@@ -169,7 +169,7 @@ describe("ChatInput", () => {
|
||||
{
|
||||
id: "project-1",
|
||||
name: "goose2",
|
||||
workingDir: "/Users/wesb/dev/goose2",
|
||||
workingDirs: ["/Users/wesb/dev/goose2"],
|
||||
},
|
||||
]}
|
||||
/>,
|
||||
|
||||
@@ -54,7 +54,7 @@ describe("ContextPanel", () => {
|
||||
<ContextPanel
|
||||
projectName="Desktop UX"
|
||||
projectColor="#22c55e"
|
||||
projectWorkingDir="/Users/test/goose2"
|
||||
projectWorkingDirs={["/Users/test/goose2"]}
|
||||
/>,
|
||||
);
|
||||
|
||||
@@ -87,7 +87,7 @@ describe("ContextPanel", () => {
|
||||
refetch: vi.fn(),
|
||||
});
|
||||
|
||||
render(<ContextPanel projectWorkingDir="/Users/test/not-a-repo" />);
|
||||
render(<ContextPanel projectWorkingDirs={["/Users/test/not-a-repo"]} />);
|
||||
|
||||
expect(screen.getByText("Not a git repository.")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -132,7 +132,7 @@ export function HomeScreen({ onStartChat, onCreateProject }: HomeScreenProps) {
|
||||
availableProjects={projects.map((project) => ({
|
||||
id: project.id,
|
||||
name: project.name,
|
||||
workingDir: project.workingDirs[0] ?? null,
|
||||
workingDirs: project.workingDirs,
|
||||
color: project.color,
|
||||
}))}
|
||||
onProjectChange={setSelectedProjectId}
|
||||
|
||||
Reference in New Issue
Block a user