Skip to content

update CreateProject to split name and path #547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ thumbs.db
.electron-vendors.cache.json

.vscode/settings.json
.env
.env
coverage/
35 changes: 18 additions & 17 deletions packages/preload/src/modules/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,27 +268,28 @@ export function initializeWorkspace(services: Services) {
const templateRepo = opts?.repo ?? EMPTY_SCENE_TEMPLATE_REPO;

try {
await fs.mkdir(projectPath, { recursive: true });
const fullName = projectPath.endsWith(name) ? projectPath : path.join(projectPath, name);
await fs.mkdir(fullName, { recursive: true });

await ipc.invoke('cli.init', projectPath, templateRepo);
await ipc.invoke('cli.init', fullName, templateRepo);

const scene = await getScene(projectPath);
const scene = await getScene(fullName);
scene.display!.title = name;

// Remove worldConfiguration for non-empty templates
if (templateRepo !== EMPTY_SCENE_TEMPLATE_REPO) {
delete scene.worldConfiguration;
}

const sceneJsonPath = path.join(projectPath, 'scene.json');
const sceneJsonPath = path.join(fullName, 'scene.json');
await fs.writeFile(sceneJsonPath, JSON.stringify(scene, null, 2));

await config.setConfig(config => {
config.workspace.paths.push(projectPath);
config.workspace.paths.push(fullName);
return config;
});

return { path: projectPath };
return { path: fullName };
} catch (error: any) {
throw new Error(`Failed to create project "${name}": ${error.message}`);
}
Expand Down Expand Up @@ -337,7 +338,8 @@ export function initializeWorkspace(services: Services) {
async function isProjectPathAvailable(projectPath: string): Promise<boolean> {
const cfg = await config.getConfig();
const [projects] = await getProjects(cfg.workspace.paths, { omitOutdatedPackages: true });
const projectAlreadyExists = projects.find($ => $.path === projectPath);
const projectPathNormalized = path.normalize(projectPath);
const projectAlreadyExists = projects.find($ => $.path === projectPathNormalized);
return !projectAlreadyExists;
}

Expand All @@ -349,15 +351,6 @@ export function initializeWorkspace(services: Services) {
defaultPath: cfg.settings.scenesPath,
});

if (!projectPath) return undefined;

const pathBaseName = path.basename(projectPath);
const isAvailable = await isProjectPathAvailable(projectPath);

if (!isAvailable) {
throw new Error(`"${pathBaseName}" is already on the projects library`);
}

return projectPath;
}

Expand All @@ -373,7 +366,15 @@ export function initializeWorkspace(services: Services) {
if (!projectPath) return undefined;

const pathBaseName = path.basename(projectPath);
if (!(await isDCL(projectPath))) {
const isAvailable = await isProjectPathAvailable(projectPath);

if (!isAvailable) {
throw new Error(`"${pathBaseName}" is already on the projects library`);
}

const isDCLProject = await isDCL(projectPath);

if (!isDCLProject) {
throw new Error(`"${pathBaseName}" is not a valid project`);
}

Expand Down
13 changes: 8 additions & 5 deletions packages/preload/tests/modules/workspace.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,26 +132,29 @@ describe('initializeWorkspace', () => {
it('should create a project with custom name and path', async () => {
const customName = 'My Custom Project';
const customPath = '/custom/path';
const fullName = services.path.join(customPath, customName);

const workspace = initializeWorkspace(services);
const result = await workspace.createProject({
name: customName,
path: customPath,
});

expect(services.fs.mkdir).toHaveBeenCalledWith(customPath, { recursive: true });
expect(services.fs.mkdir).toHaveBeenCalledWith(fullName, {
recursive: true,
});
expect(services.ipc.invoke).toHaveBeenCalledWith(
'cli.init',
customPath,
fullName,
EMPTY_SCENE_TEMPLATE_REPO,
);
expect(getScene).toHaveBeenCalledWith(customPath);
expect(getScene).toHaveBeenCalledWith(fullName);
expect(services.fs.writeFile).toHaveBeenCalledWith(
`${customPath}/scene.json`,
services.path.join(fullName, 'scene.json'),
JSON.stringify({ display: { title: customName }, worldConfiguration: {} }, null, 2),
);
expect(result).toEqual({
path: customPath,
path: fullName,
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ export function CreateProject({ open, initialValue, onClose, onSubmit }: Props)

const validate = useCallback(async () => {
setLoading(true);
const valid = await validateProjectPath(value.path);
const valid = await validateProjectPath(`${value.path}/${value.name}`);
if (!valid) setError(t('modal.create_project.errors.path_exists'));
setLoading(false);
return valid;
}, [value.path, validateProjectPath]);
}, [value, validateProjectPath]);

const handleChange = useCallback(
(key: keyof Value) => (event: React.ChangeEvent<HTMLInputElement>) => {
Expand All @@ -46,9 +46,8 @@ export function CreateProject({ open, initialValue, onClose, onSubmit }: Props)
const handleOpenFolder = useCallback(async () => {
setError(null);
setLoading(true);
const [folder, error] = await selectNewProjectPath();
const folder = await selectNewProjectPath();
setLoading(false);
if (error) return setError(t('modal.create_project.errors.path_exists'));
if (folder) setValue({ ...value, path: folder });
}, [value]);

Expand Down Expand Up @@ -93,7 +92,6 @@ export function CreateProject({ open, initialValue, onClose, onSubmit }: Props)
color="secondary"
value={value.path}
onChange={handleChange('path')}
error={!!error}
onBlur={validate}
endAdornment={
<InputAdornment position="end">
Expand Down
7 changes: 6 additions & 1 deletion packages/renderer/src/components/TemplatesPage/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,12 @@ export function TemplatesPage() {
const [data, error] = await getAvailableProject();
if (!error) {
const { name, path } = data;
setOpenModal({ type: 'create-project', payload: { name, path, repo } });
const payload = {
name,
path: path.endsWith(name) ? path.slice(0, -name.length) : path,
repo,
};
setOpenModal({ type: 'create-project', payload });
}
},
[],
Expand Down
13 changes: 8 additions & 5 deletions packages/renderer/src/hooks/useWorkspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@ export const useWorkspace = () => {
navigate('/editor');
}, []);

const createProject = useCallback((opts?: { name?: string; repo?: string; path?: string }) => {
dispatch(workspaceActions.createProjectAndInstall(opts));
navigate('/editor');
}, []);
const createProject = useCallback(
(opts: Parameters<typeof workspaceActions.createProjectAndInstall>[0]) => {
dispatch(workspaceActions.createProjectAndInstall(opts));
navigate('/editor');
},
[],
);

const deleteProject = useCallback((project: Project) => {
dispatch(workspaceActions.deleteProject(project.path));
Expand Down Expand Up @@ -75,7 +78,7 @@ export const useWorkspace = () => {
}, []);

const selectNewProjectPath = useCallback(async () => {
const result = await tryCatch(workspacePreload.selectNewProjectPath());
const result = await workspacePreload.selectNewProjectPath();
return result;
}, []);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@
"create": "Create"
},
"errors": {
"path_exists": "Path does not exist or is already in use"
"path_exists": "Path already exists"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@
"create": "Crear"
},
"errors": {
"path_exists": "La ruta no existe o ya está en uso"
"path_exists": "La ruta ya existe"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@
"create": "創建"
},
"errors": {
"path_exists": "路徑不存在或已存在"
"path_exists": "路徑已存在"
}
}
},
Expand Down
Loading