mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-06-02 10:35:37 +08:00
refactor: move project rename to module
This commit is contained in:
@@ -19,7 +19,6 @@ import { getConnectableHost } from '../shared/networkHosts.js';
|
|||||||
|
|
||||||
import { findAppRoot, getModuleDir } from './utils/runtime-paths.js';
|
import { findAppRoot, getModuleDir } from './utils/runtime-paths.js';
|
||||||
import {
|
import {
|
||||||
renameProjectById,
|
|
||||||
deleteSessionById,
|
deleteSessionById,
|
||||||
deleteProjectById,
|
deleteProjectById,
|
||||||
getProjectPathById,
|
getProjectPathById,
|
||||||
@@ -302,17 +301,6 @@ app.post('/api/system/update', authenticateToken, async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Rename project endpoint; stores the custom name on the DB row for `projectId`.
|
|
||||||
app.put('/api/projects/:projectId/rename', authenticateToken, async (req, res) => {
|
|
||||||
try {
|
|
||||||
const { displayName } = req.body;
|
|
||||||
await renameProjectById(req.params.projectId, displayName);
|
|
||||||
res.json({ success: true });
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({ error: error.message });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete session endpoint; resolves `projectId` to path before touching disk.
|
// Delete session endpoint; resolves `projectId` to path before touching disk.
|
||||||
app.delete('/api/projects/:projectId/sessions/:sessionId', authenticateToken, async (req, res) => {
|
app.delete('/api/projects/:projectId/sessions/:sessionId', authenticateToken, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
|
|
||||||
import { createProject } from '@/modules/projects/services/project-management.service.js';
|
import { createProject, updateProjectDisplayName } from '@/modules/projects/services/project-management.service.js';
|
||||||
import { startCloneProject } from '@/modules/projects/services/project-clone.service.js';
|
import { startCloneProject } from '@/modules/projects/services/project-clone.service.js';
|
||||||
import { getProjectTaskMaster } from '@/modules/projects/services/projects-has-taskmaster.service.js';
|
import { getProjectTaskMaster } from '@/modules/projects/services/projects-has-taskmaster.service.js';
|
||||||
import { AppError, asyncHandler } from '@/shared/utils.js';
|
import { AppError, asyncHandler } from '@/shared/utils.js';
|
||||||
@@ -166,4 +166,15 @@ router.get(
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
router.put('/:projectId/rename', (req, res) => {
|
||||||
|
try {
|
||||||
|
const projectId = typeof req.params.projectId === 'string' ? req.params.projectId : '';
|
||||||
|
const { displayName } = req.body as { displayName?: unknown };
|
||||||
|
updateProjectDisplayName(projectId, displayName);
|
||||||
|
res.json({ success: true });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to rename project' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@@ -140,3 +140,11 @@ export async function createProject(
|
|||||||
project: mapProjectRowToApiView(projectRow),
|
project: mapProjectRowToApiView(projectRow),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets `projects.custom_project_name` for the given `projectId` (or clears it when empty).
|
||||||
|
*/
|
||||||
|
export function updateProjectDisplayName(projectId: string, newDisplayName: unknown): void {
|
||||||
|
const trimmed = typeof newDisplayName === 'string' ? newDisplayName.trim() : '';
|
||||||
|
projectsDb.updateCustomProjectNameById(projectId, trimmed.length > 0 ? trimmed : null);
|
||||||
|
}
|
||||||
|
|||||||
@@ -666,57 +666,6 @@ async function getSessionMessages(projectName, sessionId, limit = null, offset =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rename a project's display name
|
|
||||||
async function renameProject(projectName, newDisplayName) {
|
|
||||||
const config = await loadProjectConfig();
|
|
||||||
|
|
||||||
if (!newDisplayName || newDisplayName.trim() === '') {
|
|
||||||
// Remove custom name if empty, will fall back to auto-generated
|
|
||||||
if (config[projectName]) {
|
|
||||||
delete config[projectName].displayName;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Set custom display name, preserving other properties (manuallyAdded, originalPath)
|
|
||||||
config[projectName] = {
|
|
||||||
...config[projectName],
|
|
||||||
displayName: newDisplayName.trim()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
await saveProjectConfig(config);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ID-based wrapper around `renameProject`.
|
|
||||||
*
|
|
||||||
* Writes the new display name to the `projects.custom_project_name` column
|
|
||||||
* (the source of truth for the DB-driven getProjectsWithSessions() response) and also
|
|
||||||
* keeps the legacy project-config.json in sync for backwards compatibility
|
|
||||||
* with any code that still reads it.
|
|
||||||
*/
|
|
||||||
async function renameProjectById(projectId, newDisplayName) {
|
|
||||||
const projectPath = await getProjectPathById(projectId);
|
|
||||||
if (!projectPath) {
|
|
||||||
throw new Error(`Unknown projectId: ${projectId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const trimmed = typeof newDisplayName === 'string' ? newDisplayName.trim() : '';
|
|
||||||
// Persist on the DB row so getProjectsWithSessions() immediately reflects the change.
|
|
||||||
projectsDb.updateCustomProjectNameById(projectId, trimmed.length > 0 ? trimmed : null);
|
|
||||||
|
|
||||||
// Keep the legacy file-based project config in lockstep so historic readers
|
|
||||||
// that still consult project-config.json don't diverge.
|
|
||||||
const claudeFolderName = claudeFolderNameFromPath(projectPath);
|
|
||||||
try {
|
|
||||||
await renameProject(claudeFolderName, trimmed);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn(`[projects] Legacy renameProject sync failed for ${projectId}:`, error.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID-based wrapper around `deleteSession`.
|
* ID-based wrapper around `deleteSession`.
|
||||||
*
|
*
|
||||||
@@ -2030,11 +1979,10 @@ async function getGeminiCliSessionMessages(sessionId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only functions with consumers outside this module are exported. Folder-name
|
// Only functions with consumers outside this module are exported. Folder-name
|
||||||
// based helpers (`getSessions`, `renameProject`, `deleteSession`, etc.) are
|
// based helpers (`getSessions`, `deleteSession`, etc.) are kept as internal
|
||||||
// kept as internal implementation details of the id-based wrappers below.
|
// implementation details of the id-based wrappers below.
|
||||||
export {
|
export {
|
||||||
getSessionMessages,
|
getSessionMessages,
|
||||||
renameProjectById,
|
|
||||||
deleteSessionById,
|
deleteSessionById,
|
||||||
deleteProjectById,
|
deleteProjectById,
|
||||||
addProjectManually,
|
addProjectManually,
|
||||||
|
|||||||
Reference in New Issue
Block a user