feat: add bulk delete functionality for features

- Introduced a new endpoint `/bulk-delete` to allow deletion of multiple features at once.
- Implemented `createBulkDeleteHandler` to process bulk delete requests and handle success/failure responses.
- Updated the UI to include a bulk delete option in the BoardView component, with confirmation dialog for user actions.
- Enhanced the HTTP API client to support bulk delete requests.
- Improved the selection action bar to trigger bulk delete functionality and provide user feedback.
This commit is contained in:
Shirone
2026-01-11 10:17:35 +01:00
parent 2d4ffc7514
commit 9c5fe44617
5 changed files with 223 additions and 43 deletions

View File

@@ -10,6 +10,7 @@ import { createGetHandler } from './routes/get.js';
import { createCreateHandler } from './routes/create.js';
import { createUpdateHandler } from './routes/update.js';
import { createBulkUpdateHandler } from './routes/bulk-update.js';
import { createBulkDeleteHandler } from './routes/bulk-delete.js';
import { createDeleteHandler } from './routes/delete.js';
import { createAgentOutputHandler, createRawOutputHandler } from './routes/agent-output.js';
import { createGenerateTitleHandler } from './routes/generate-title.js';
@@ -26,6 +27,11 @@ export function createFeaturesRoutes(featureLoader: FeatureLoader): Router {
validatePathParams('projectPath'),
createBulkUpdateHandler(featureLoader)
);
router.post(
'/bulk-delete',
validatePathParams('projectPath'),
createBulkDeleteHandler(featureLoader)
);
router.post('/delete', validatePathParams('projectPath'), createDeleteHandler(featureLoader));
router.post('/agent-output', createAgentOutputHandler(featureLoader));
router.post('/raw-output', createRawOutputHandler(featureLoader));

View File

@@ -0,0 +1,62 @@
/**
* POST /bulk-delete endpoint - Delete multiple features at once
*/
import type { Request, Response } from 'express';
import { FeatureLoader } from '../../../services/feature-loader.js';
import { getErrorMessage, logError } from '../common.js';
interface BulkDeleteRequest {
projectPath: string;
featureIds: string[];
}
interface BulkDeleteResult {
featureId: string;
success: boolean;
error?: string;
}
export function createBulkDeleteHandler(featureLoader: FeatureLoader) {
return async (req: Request, res: Response): Promise<void> => {
try {
const { projectPath, featureIds } = req.body as BulkDeleteRequest;
if (!projectPath || !featureIds || !Array.isArray(featureIds) || featureIds.length === 0) {
res.status(400).json({
success: false,
error: 'projectPath and featureIds (non-empty array) are required',
});
return;
}
const results: BulkDeleteResult[] = [];
for (const featureId of featureIds) {
try {
const success = await featureLoader.delete(projectPath, featureId);
results.push({ featureId, success });
} catch (error) {
results.push({
featureId,
success: false,
error: getErrorMessage(error),
});
}
}
const successCount = results.filter((r) => r.success).length;
const failureCount = results.filter((r) => !r.success).length;
res.json({
success: failureCount === 0,
deletedCount: successCount,
failedCount: failureCount,
results,
});
} catch (error) {
logError(error, 'Bulk delete features failed');
res.status(500).json({ success: false, error: getErrorMessage(error) });
}
};
}