From 72a0e256a89aa29cae8287ddfa17bca9e8e5c20e Mon Sep 17 00:00:00 2001 From: dotta Date: Thu, 19 Mar 2026 07:17:49 -0500 Subject: [PATCH] Simplify new project dialog: always show repo and local folder fields Remove the workspace setup toggle menu ("Where will work be done on this project?") and instead always display both repo URL and local folder inputs directly. Both fields are marked as optional with help tooltips explaining their purpose. Repo is shown first, local folder second. Co-Authored-By: Paperclip --- ui/src/components/NewProjectDialog.tsx | 162 +++++++++---------------- 1 file changed, 56 insertions(+), 106 deletions(-) diff --git a/ui/src/components/NewProjectDialog.tsx b/ui/src/components/NewProjectDialog.tsx index 6378dfda..6a449b52 100644 --- a/ui/src/components/NewProjectDialog.tsx +++ b/ui/src/components/NewProjectDialog.tsx @@ -23,10 +23,13 @@ import { Calendar, Plus, X, - FolderOpen, - Github, - GitBranch, + HelpCircle, } from "lucide-react"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { PROJECT_COLORS } from "@paperclipai/shared"; import { cn } from "../lib/utils"; import { MarkdownEditor, type MarkdownEditorRef } from "./MarkdownEditor"; @@ -41,8 +44,6 @@ const projectStatuses = [ { value: "cancelled", label: "Cancelled" }, ]; -type WorkspaceSetup = "none" | "local" | "repo" | "both"; - export function NewProjectDialog() { const { newProjectOpen, closeNewProject } = useDialog(); const { selectedCompanyId, selectedCompany } = useCompany(); @@ -53,7 +54,6 @@ export function NewProjectDialog() { const [goalIds, setGoalIds] = useState([]); const [targetDate, setTargetDate] = useState(""); const [expanded, setExpanded] = useState(false); - const [workspaceSetup, setWorkspaceSetup] = useState("none"); const [workspaceLocalPath, setWorkspaceLocalPath] = useState(""); const [workspaceRepoUrl, setWorkspaceRepoUrl] = useState(""); const [workspaceError, setWorkspaceError] = useState(null); @@ -87,7 +87,6 @@ export function NewProjectDialog() { setGoalIds([]); setTargetDate(""); setExpanded(false); - setWorkspaceSetup("none"); setWorkspaceLocalPath(""); setWorkspaceRepoUrl(""); setWorkspaceError(null); @@ -124,23 +123,16 @@ export function NewProjectDialog() { } }; - const toggleWorkspaceSetup = (next: WorkspaceSetup) => { - setWorkspaceSetup((prev) => (prev === next ? "none" : next)); - setWorkspaceError(null); - }; - async function handleSubmit() { if (!selectedCompanyId || !name.trim()) return; - const localRequired = workspaceSetup === "local" || workspaceSetup === "both"; - const repoRequired = workspaceSetup === "repo" || workspaceSetup === "both"; const localPath = workspaceLocalPath.trim(); const repoUrl = workspaceRepoUrl.trim(); - if (localRequired && !isAbsolutePath(localPath)) { + if (localPath && !isAbsolutePath(localPath)) { setWorkspaceError("Local folder must be a full absolute path."); return; } - if (repoRequired && !isGitHubRepoUrl(repoUrl)) { + if (repoUrl && !isGitHubRepoUrl(repoUrl)) { setWorkspaceError("Repo must use a valid GitHub repo URL."); return; } @@ -157,28 +149,15 @@ export function NewProjectDialog() { ...(targetDate ? { targetDate } : {}), }); - const workspacePayloads: Array> = []; - if (localRequired && repoRequired) { - workspacePayloads.push({ - name: deriveWorkspaceNameFromPath(localPath), - cwd: localPath, - repoUrl, - }); - } else if (localRequired) { - workspacePayloads.push({ - name: deriveWorkspaceNameFromPath(localPath), - cwd: localPath, - }); - } else if (repoRequired) { - workspacePayloads.push({ - name: deriveWorkspaceNameFromRepo(repoUrl), - repoUrl, - }); - } - for (const workspacePayload of workspacePayloads) { - await projectsApi.createWorkspace(created.id, { - ...workspacePayload, - }); + if (localPath || repoUrl) { + const workspacePayload: Record = { + name: localPath + ? deriveWorkspaceNameFromPath(localPath) + : deriveWorkspaceNameFromRepo(repoUrl), + ...(localPath ? { cwd: localPath } : {}), + ...(repoUrl ? { repoUrl } : {}), + }; + await projectsApi.createWorkspace(created.id, workspacePayload); } queryClient.invalidateQueries({ queryKey: queryKeys.projects.list(selectedCompanyId) }); @@ -280,80 +259,51 @@ export function NewProjectDialog() {
-
-

Where will work be done on this project?

-

Add a repo and/or local folder for this project.

-
-
- - - +
+
+ + optional + + + + + + Link a GitHub repository so agents can clone, read, and push code for this project. + + +
+ { setWorkspaceRepoUrl(e.target.value); setWorkspaceError(null); }} + placeholder="https://github.com/org/repo" + />
- {(workspaceSetup === "local" || workspaceSetup === "both") && ( -
- -
- setWorkspaceLocalPath(e.target.value)} - placeholder="/absolute/path/to/workspace" - /> - -
+
+
+ + optional + + + + + + Set an absolute path on this machine where local agents will read and write files for this project. + +
- )} - {(workspaceSetup === "repo" || workspaceSetup === "both") && ( -
- +
setWorkspaceRepoUrl(e.target.value)} - placeholder="https://github.com/org/repo" + className="w-full rounded border border-border bg-transparent px-2 py-1 text-xs font-mono outline-none" + value={workspaceLocalPath} + onChange={(e) => { setWorkspaceLocalPath(e.target.value); setWorkspaceError(null); }} + placeholder="/absolute/path/to/workspace" /> +
- )} +
+ {workspaceError && (

{workspaceError}

)}