Repository navigation
feat(desktop): create blank projects from Superset - #5906
Conversation
📝 WalkthroughWalkthroughAdds an empty-project creation modal with V1/V2 creation paths, directory selection, promise-based modal state, and new entry points across the command palette, dashboards, sidebars, project picker, and onboarding flow. ChangesEmpty project creation
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant EntryPoint
participant EmptyProjectModal
participant ProjectCreation
participant Workspace
User->>EntryPoint: Select Create new project
EntryPoint->>EmptyProjectModal: Open modal
User->>EmptyProjectModal: Submit name and location
EmptyProjectModal->>ProjectCreation: Create and initialize project
ProjectCreation-->>EmptyProjectModal: Return projectId
EmptyProjectModal->>Workspace: Resolve project and navigate
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/desktop/src/renderer/react-query/projects/useCreateV1Project.ts (1)
10-17: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate try/catch/toast pattern between
cloneFromUrlandcreateEmpty.Both callbacks repeat the same "call mutation → check
result.success→ toast/return null → invalidate recents → catch/toast" shape. Consider extracting a shared helper to reduce duplication and keep error-toast wording in one place.♻️ Example helper extraction
+ const runCreate = useCallback( + async <T extends { success: boolean; error?: string; project: { id: string } }>( + mutateAsync: () => Promise<T>, + ): Promise<string | null> => { + try { + const result = await mutateAsync(); + if (!result.success) { + toast.error("Could not create project", { description: result.error }); + return null; + } + await utils.projects.getRecents.invalidate(); + return result.project.id; + } catch (err) { + toast.error("Could not create project", { + description: err instanceof Error ? err.message : String(err), + }); + return null; + } + }, + [utils], + );Also applies to: 51-78
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/desktop/src/renderer/react-query/projects/useCreateV1Project.ts` around lines 10 - 17, Extract the shared mutation error-handling, success validation, toast, and recents-invalidation flow from cloneFromUrl and createEmpty into a reusable helper within useCreateV1Project. Update both callbacks to use the helper while preserving their mutation-specific inputs and existing error-toast wording.apps/desktop/src/renderer/routes/_authenticated/components/EmptyProjectModal/EmptyProjectModal.tsx (1)
93-103: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winV1 failure path bypasses the
onErrorcontract.When
createV1Project.createEmptyfails, this branch justreturns — the caller-suppliedonError(which formats "Create failed: …" perAddRepositoryModals.tsx) is never invoked, only the internal toast fromuseCreateV1Project. The V2 branch below does honoronError. Result: users see differently-worded error toasts depending onisV2CloudEnabled, and any consumer relying ononErrorfor custom handling silently loses v1 failures.Consider having
createEmptyreturn the error message (or surface it) so this component can route it throughonError/fallback toast consistently with the v2 branch.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/desktop/src/renderer/routes/_authenticated/components/EmptyProjectModal/EmptyProjectModal.tsx` around lines 93 - 103, Update the V1 failure handling in the createEmpty flow to surface the failure message from createV1Project.createEmpty, then pass it through the component’s onError contract (with the existing fallback toast behavior) before returning. Preserve the current success flow and align the resulting error handling with the V2 branch.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx`:
- Around line 67-70: Update handleNewProject to await the promise returned by
openEmptyProject, then pass the resulting projectId into the existing
workspace-selection/creation flow after closing NewWorkspaceModal. Preserve the
current modal-closing behavior and reuse the established selection/creation
handler rather than discarding the project result.
---
Nitpick comments:
In `@apps/desktop/src/renderer/react-query/projects/useCreateV1Project.ts`:
- Around line 10-17: Extract the shared mutation error-handling, success
validation, toast, and recents-invalidation flow from cloneFromUrl and
createEmpty into a reusable helper within useCreateV1Project. Update both
callbacks to use the helper while preserving their mutation-specific inputs and
existing error-toast wording.
In
`@apps/desktop/src/renderer/routes/_authenticated/components/EmptyProjectModal/EmptyProjectModal.tsx`:
- Around line 93-103: Update the V1 failure handling in the createEmpty flow to
surface the failure message from createV1Project.createEmpty, then pass it
through the component’s onError contract (with the existing fallback toast
behavior) before returning. Preserve the current success flow and align the
resulting error handling with the V2 branch.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: d06e3685-8b1a-492d-bf6b-ecf455ff7384
📒 Files selected for processing (14)
apps/desktop/src/renderer/commandPalette/modules/addProject/commands.tsxapps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsxapps/desktop/src/renderer/react-query/projects/useCreateV1Project.tsapps/desktop/src/renderer/routes/_authenticated/_dashboard/components/AddRepositoryModals/AddRepositoryModals.tsxapps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarHeader/DashboardSidebarHeader.tsxapps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspacesHeader/DashboardSidebarWorkspacesHeader.tsxapps/desktop/src/renderer/routes/_authenticated/components/DashboardNewWorkspaceModal/components/DashboardNewWorkspaceForm/PromptGroup/components/ProjectPickerPill/ProjectPickerPill.tsxapps/desktop/src/renderer/routes/_authenticated/components/EmptyProjectModal/EmptyProjectModal.tsxapps/desktop/src/renderer/routes/_authenticated/components/EmptyProjectModal/index.tsapps/desktop/src/renderer/routes/_authenticated/onboarding/layout.tsxapps/desktop/src/renderer/routes/_authenticated/onboarding/project/page.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/WorkspaceSidebarFooter.tsxapps/desktop/src/renderer/stores/add-repository-modal.test.tsapps/desktop/src/renderer/stores/add-repository-modal.ts
8244443 to
50224eb
Compare
The wrapper re-implemented the fallback toast that useCreateV1Project's runCreate already provides. Claude-Session: https://claude.ai/code/session_01539kWVLWyz9MUrFvEWybZx
50224eb to
c5a6b5a
Compare
What & why
Superset can clone a repository, open an existing folder, or start from a template, but it cannot create a blank project for someone starting an app from scratch.
This adds a first-class Create new project action to the new-workspace picker, project menus, command palette, legacy workspace flow, and onboarding. The new modal creates a named folder, initializes a Git repository on
mainwith an initial commit, registers the project, and makes it available for workspace creation without leaving Superset. It uses the existing host-service empty-project mode and adds the equivalent v1 desktop path.How I tested it
bun run lint— passed with no warningsbun run typecheck— 35/35 tasks passedcd apps/desktop && bun test src/renderer/stores/add-repository-modal.test.ts— 2/2 passedcd packages/host-service && bun test test/integration/project-setup.integration.test.ts— 8/8 passedhttp://localhost:3085: New Workspace → project picker → Create new project → enter name/location → Create project → select No agent → create workspace. Verified the resulting folder is a Git repository onmainwith an initial commit and no remote, and that Superset created and opened the workspace.Screenshots
Create new project entry point
Blank project form
Created project and workspace
Checklist
type(scope): subject)bun run lintandbun run typecheckpass (CI fails on lint warnings too)Summary by cubic
Adds a “Create new project” flow to the desktop app so users can start from a blank folder without leaving Superset. Creates a named directory, initializes a Git repo on
mainwith an initial commit, registers the project, and returns users to workspace creation with the project selected.New Features
EmptyProjectModalto name a project and pick a location, with browse, progress, and error toasts.electronTrpc.projects.createEmptyRepoand host-serviceproject.create(empty mode); invalidatesprojects.getRecentsand finalizes setup.empty-projectviauseOpenEmptyProjectModal, ensures only one add-project modal at a time, and workspace/onboarding flows preselect the newly created project.Refactors
runCreateandonErrorpassthrough inuseCreateV1Project; unified pending state withcreateEmptyRepo.Written for commit c5a6b5a. Summary will update on new commits.
Summary by CodeRabbit