diff --git a/e2e/playwright/onboarding-tests.spec.ts b/e2e/playwright/onboarding-tests.spec.ts index 84288213b..6bee39f40 100644 --- a/e2e/playwright/onboarding-tests.spec.ts +++ b/e2e/playwright/onboarding-tests.spec.ts @@ -425,7 +425,9 @@ test( const restartConfirmationButton = page.getByRole('button', { name: 'Make a new project', }) - const tutorialProjectIndicator = page.getByText('Tutorial Project 00') + const tutorialProjectIndicator = page + .getByTestId('project-sidebar-toggle') + .filter({ hasText: 'Tutorial Project 00' }) const tutorialModalText = page.getByText('Welcome to Modeling App!') const tutorialDismissButton = page.getByRole('button', { name: 'Dismiss' }) const userMenuButton = page.getByTestId('user-sidebar-toggle') diff --git a/e2e/playwright/projects.spec.ts b/e2e/playwright/projects.spec.ts index a27d26faf..16b174c09 100644 --- a/e2e/playwright/projects.spec.ts +++ b/e2e/playwright/projects.spec.ts @@ -507,17 +507,18 @@ test( 'File in the file pane should open with a single click', { tag: '@electron' }, async ({ browserName }, testInfo) => { + const projectName = 'router-template-slate' const { electronApp, page } = await setupElectron({ testInfo, folderSetupFn: async (dir) => { - await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true }) + await fsp.mkdir(`${dir}/${projectName}`, { recursive: true }) await fsp.copyFile( 'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl', - `${dir}/router-template-slate/main.kcl` + `${dir}/${projectName}/main.kcl` ) await fsp.copyFile( 'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl', - `${dir}/router-template-slate/otherThingToClickOn.kcl` + `${dir}/${projectName}/otherThingToClickOn.kcl` ) }, }) @@ -526,7 +527,7 @@ test( page.on('console', console.log) - await page.getByText('router-template-slate').click() + await page.getByText(projectName).click() await expect(page.getByTestId('loading')).toBeAttached() await expect(page.getByTestId('loading')).not.toBeAttached({ timeout: 20_000, diff --git a/e2e/playwright/text-to-cad-tests.spec.ts b/e2e/playwright/text-to-cad-tests.spec.ts index af14f7cd9..906ffc405 100644 --- a/e2e/playwright/text-to-cad-tests.spec.ts +++ b/e2e/playwright/text-to-cad-tests.spec.ts @@ -710,7 +710,9 @@ test( await page.setViewportSize({ width: 1200, height: 500 }) // Locators - const projectMenuButton = page.getByRole('button', { name: projectName }) + const projectMenuButton = page + .getByTestId('project-sidebar-toggle') + .filter({ hasText: projectName }) const textToCadFileButton = page.getByRole('listitem').filter({ has: page.getByRole('button', { name: textToCadFileName }), }) diff --git a/src/components/FileTree.tsx b/src/components/FileTree.tsx index b8b08019b..1e534bdb6 100644 --- a/src/components/FileTree.tsx +++ b/src/components/FileTree.tsx @@ -538,3 +538,19 @@ export const FileTreeInner = ({ ) } + +export const FileTreeRoot = () => { + const loaderData = useRouteLoaderData(PATHS.FILE) as IndexLoaderData + const { project } = loaderData + + // project.path should never be empty here but I guess during initial loading + // it can be. + return ( +
+ {project?.name ?? ''} +
+ ) +} diff --git a/src/components/HelpMenu.tsx b/src/components/HelpMenu.tsx index 8893b02e7..6aecec713 100644 --- a/src/components/HelpMenu.tsx +++ b/src/components/HelpMenu.tsx @@ -4,7 +4,7 @@ import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext' import { CustomIcon } from './CustomIcon' import { useLocation, useNavigate } from 'react-router-dom' import { PATHS } from 'lib/paths' -import { createAndOpenNewProject } from 'lib/desktopFS' +import { createAndOpenNewTutorialProject } from 'lib/desktopFS' import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath' import { useLspContext } from './LspProvider' import { openExternalBrowserIfDesktop } from 'lib/openWindow' @@ -116,9 +116,10 @@ export function HelpMenu(props: React.PropsWithChildren) { if (isInProject) { navigate(filePath + PATHS.ONBOARDING.INDEX) } else { - createAndOpenNewProject({ onProjectOpen, navigate }).catch( - reportRejection - ) + createAndOpenNewTutorialProject({ + onProjectOpen, + navigate, + }).catch(reportRejection) } }} > diff --git a/src/components/ModelingSidebar/ModelingPane.tsx b/src/components/ModelingSidebar/ModelingPane.tsx index 068c63995..a5ffc079f 100644 --- a/src/components/ModelingSidebar/ModelingPane.tsx +++ b/src/components/ModelingSidebar/ModelingPane.tsx @@ -1,3 +1,4 @@ +import { ReactNode } from 'react' import styles from './ModelingPane.module.css' import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext' import { ActionButton } from 'components/ActionButton' @@ -6,22 +7,24 @@ import { CustomIconName } from 'components/CustomIcon' import { IconDefinition } from '@fortawesome/free-solid-svg-icons' import { ActionIcon } from 'components/ActionIcon' -export interface ModelingPaneProps - extends React.PropsWithChildren, - React.HTMLAttributes { +export interface ModelingPaneProps { + id: string + children: ReactNode | ReactNode[] + className?: string icon?: CustomIconName | IconDefinition - title: string + title: ReactNode Menu?: React.ReactNode | React.FC detailsTestId?: string onClose: () => void } export const ModelingPaneHeader = ({ + id, icon, title, Menu, onClose, -}: Pick) => { +}: Pick) => { return (
@@ -34,7 +37,7 @@ export const ModelingPaneHeader = ({ bgClassName="!bg-transparent" /> )} - {title} + {title}
{Menu instanceof Function ? : Menu} , + sidebarName: 'Project Files', icon: 'folder', Content: FileTreeInner, keybinding: 'Shift + F', diff --git a/src/components/ModelingSidebar/ModelingSidebar.tsx b/src/components/ModelingSidebar/ModelingSidebar.tsx index 8ca551808..81a3ee202 100644 --- a/src/components/ModelingSidebar/ModelingSidebar.tsx +++ b/src/components/ModelingSidebar/ModelingSidebar.tsx @@ -5,6 +5,7 @@ import { useCallback, useEffect, useMemo, + ReactNode, useContext, } from 'react' import { useHotkeys } from 'react-hotkeys-hook' @@ -270,7 +271,8 @@ interface ModelingPaneButtonProps extends React.HTMLAttributes { paneConfig: { id: string - title: string + title: ReactNode + sidebarName?: string icon: CustomIconName | IconDefinition keybinding: string iconClassName?: string @@ -299,7 +301,10 @@ function ModelingPaneButton({