Turn your 2-sentence ticket into a detailed plan that lets you Vibe Code waaay faster
See how Task Demon transforms your brief task description into an incredibly detailed, context-rich implementation prompt with all the project-specific information needed for successful implementation.
Your Simple Request
You start with a brief description of what you want to build. This is all the information you need to provide – a single paragraph in plain language that outlines the feature you want.

Comprehensive Implementation Prompt
Task Demon expands your simple request into a detailed implementation prompt that automatically includes all of the important context about your project - automatically gleaned by Task Demon's Characterization process.
Here's what that ticket entered as a chatbot message ended up looking like:
<purpose>
You are an experienced senior software engineer working on a code repository.
You will be given details about the Project (which represents the repository), including any existing
high-level documentation about the Project.You are being given a detailed plan for some work that needs to be done, including tasks, files, and instructions.
The plan has been prepared for you ahead of time by an LLM Architect, and then checked and improved
by a second Architect. It is likely that the plan is good and you should follow it as closely as possible to completion.Implement the changes described in the plan, following sequentially task by task until the work is complete.
</purpose>
<instructions>
<instruction>Implement all of the tasks in the plan, one by one, in the order specified</instruction>
<instruction>For each task, ensure that the work has been completed according to the instructions in the plan</instruction>
<instruction>Use the tools available to you to examine files in the repository if it helps you make your determination</instruction>
<instruction>Read existing code and comments first, and reuse code where possible</instruction>
<instruction>This is a Next JS application using React and TypeScript. Use those technologies.</instruction>
</instructions>
<data>
Here is an overview of the project you are working on:
<project>
<id>83ad8f85-e269-4fbb-ace5-1d99eb4ca87a</id>
<name>Task Demon</name>
<description>Task Demon is a chatbot-centric SaaS application that acts on behalf of the user to create and maintain tickets (or issues) for work that needs to be done. It also has a number of Agents that can be run on customer devices to automatically use AI to triage, plan and implement work on git repositories.</description>
<status>active</status>
</project>
Here is some background information about this task in the context of the project:
<project-document>
# Task Demon: Add Reset Button to Project Details Page
## Project Overview
**Project Name:** Task Demon
**Project ID:** 2d1b9dd6-a737-4b43-9c2a-6f6323908cb5
**Description:** Task Demon is a chatbot-centric SaaS application designed to automate software development workflows. It acts as an AI-powered task management system that creates and maintains tickets for work that needs to be done. The platform includes specialized AI agents that run on customer devices to automatically triage, plan, and implement work on git repositories. Task Demon integrates deeply with GitHub, providing a seamless experience for managing development tasks.
## Task Details
**Task ID:** eecc9da4-ae5e-4084-84b3-72a6ccbd817f
**Task Name:** Add Reset Button to Project Details Page
**Task Description:** Implement a button on the Project Details page that allows users to reset the project. This button should trigger a new API endpoint that calls a library function to delete all documents, tasks, characterizations, events, workflows, agents, chats, messages, and instructions for the project. Additionally, it should set `tasksImported` to false on the project. The reset option should be accessible via a button in the Project Settings page, which opens a confirmation modal to verify the action due to its destructive nature. After the reset is complete, the modal should inform the user of the success and provide a button to 'Go to Project'.
## Relevant Information from Project Documents
### Project Details Page Characterization
- **Core Components:**
- **Server Components:** Located in `app/app/projects/[projectId]`, including:
- `page.tsx`: Main server component that fetches and renders project data.
- `layout.tsx`: Provides ProjectProvider context to child components.
- **Client Components:** Primarily in `components/projects/`, structured as:
- Project header (title, description).
- Settings panel (preferences, GitHub integration).
- Characterization summary section.
- Task list with filtering capabilities.
- Project chat interface.
- Activity feed with real-time updates.
- Documents section organized by type.
- Project agents section.
- **State Management:**
- `ProjectProvider`: Provides project data and UI preferences.
- `use-project-context.tsx`: Context hook managing project state.
- Custom hooks for real-time data synchronization:
- `use-project-events.ts`: Manages project activity with pagination.
- `use-project-events-swr.ts`: Handles real-time updates via Pusher.
- **Data Flow:**
- **Initial Load:** Server fetches project data, tasks, and characterization status.
- **Real-time Updates:** Pusher channels provide WebSocket-based notifications.
- **User Interactions:** Edit project metadata, start/view characterization, filter and view tasks, chat with project AI, monitor activity feed.
### API Documentation
- **Projects API:**
- `/api/projects/:projectId`: Get project details.
- `/api/projects/:projectId/tasks`: List project tasks.
- `/api/projects/:projectId/characterization`: Get project characterization.
- **New Endpoint Required:** A new API endpoint will be needed to handle the reset functionality, which will delete all related data and reset `tasksImported`.
### Security and Compliance
- **Authentication and Access Control:**
- All routes under `/app/*` are protected by middleware.
- Unauthenticated users are redirected to the login page.
- Secure URL handling with proper validation.
- **Data Handling and Storage:**
- User data stored on Vercel's infrastructure.
- All API communication uses HTTPS.
- WebSocket connections secured with WSS.
### UI Technical Documentation
- **Component Architecture:**
- **Base UI Components:** Foundational elements like Button, Input, Badge, Dialog.
- **Composite Components:** Built from UI primitives.
- **Feature Components:** Project components located in `/components/projects/`.
- **Design System:**
- Theme-aware colors adapting to light/dark modes.
- Semantic color naming and CSS variables implemented through Tailwind.
- **UI Patterns and Conventions:**
- TypeScript interfaces for component props.
- Forwarded refs for better composition.
- Consistent variant and size props.
### Pusher Integration
- **Real-time Communication:**
- Pusher channels for project, task, and characterization-specific events.
- WebSockets for streaming AI agent responses.
### Testing and Quality Assurance
- **Testing Frameworks:**
- **Jest:** Primary testing framework for both backend and frontend.
- **@testing-library/react:** Library for testing React components.
- **Testing Methodologies:**
- Unit Testing, Integration Testing, UI Testing, API Testing.
## Implementation Considerations
1. **UI Design:**
- Add a "Reset Project" button to the Project Settings page.
- Implement a confirmation modal to verify the reset action due to its destructive nature.
- After reset, display a success message with a button to 'Go to Project'.
2. **API Development:**
- Develop a new API endpoint to handle the reset functionality.
- Ensure the endpoint deletes all related data (documents, tasks, characterizations, events, workflows, agents, chats, messages, and instructions) and sets `tasksImported` to false.
3. **Security:**
- Ensure the reset action is protected by proper authentication and authorization checks.
- Implement secure data handling practices as per the security documentation.
4. **Testing:**
- Write unit and integration tests for the new API endpoint.
- Test the UI components for the reset button and confirmation modal.
- Ensure real-time updates are handled correctly post-reset.
5. **Real-time Updates:**
- Use Pusher to notify the UI of changes post-reset, ensuring the user interface reflects the reset state immediately.
By following these guidelines and utilizing the provided documentation, the task of adding a reset button to the Project Details page can be implemented effectively, ensuring a seamless user experience and maintaining the integrity of the Task Demon platform.
</project-document>
This is the task itself:
<task>
<id>eecc9da4-ae5e-4084-84b3-72a6ccbd817f</id>
<name>Add Reset Button to Project Details Page</name>
<description>Implement a button on the Project Details page that allows users to reset the project. This button should trigger a new API endpoint that calls a library function to delete all documents, tasks, characterizations, events, workflows, agents, chats, messages, and instructions for the project. Additionally, it should set `tasksImported` to false on the project. The reset option should be accessible via a button in the Project Settings page, which opens a confirmation modal to verify the action due to its destructive nature. After the reset is complete, the modal should inform the user of the success and provide a button to 'Go to Project'.</description>
<status>closed</status>
</task>
Here is the plan for the work:
<plan>
I'll analyze the task of adding a reset button to the Project Details page and create a comprehensive requirements document. Let me start by understanding the task and existing codebase.
# Requirements Document: Add Reset Button to Project Details Page
## Overview of Approach
This task involves adding a reset functionality to the Project Details page, which requires both frontend components and backend services. I'll need to:
1. Create a new API endpoint for resetting a project
2. Implement library functions to handle data deletion operations
3. Add a reset button to the Project Settings component
4. Create a confirmation dialog for the reset action
5. Create a success notification after reset completion
The reset operation is destructive, removing all associated project data (documents, tasks, characterizations, events, workflows, agents, chats, messages, and instructions) while maintaining the project itself. Given the severity of this action, proper user confirmation and security checks are essential.
This implementation will follow the existing patterns in the Task Demon application, leveraging the ShadCN UI component library, Next.js App Router, and Drizzle ORM.
## Architectural Overview
### System Components
The reset project functionality will span several architectural layers:
1. **UI Layer**:
- A reset button in the Project Settings panel
- A confirmation dialog using the existing ConfirmationDialog component
- Success notification via the toast system
2. **API Layer**:
- A new REST endpoint at `/api/projects/[projectId]/reset` that handles the project reset request
- Authentication and authorization middleware to ensure only authorized users can reset projects
3. **Data Layer**:
- Library functions to delete associated data across multiple tables
- Database queries using Drizzle ORM to perform the deletions
- Project update to reset the `tasksImported` flag
4. **Notification Layer**:
- Pusher integration to notify UI components of the reset completion
- Real-time updates to reflect the project's new state
### Data Flow
```
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ │ │ │ │ │
│ Project Settings │────►│ Reset API Endpoint│────►│ Reset Functions │
│ + Reset Button │ │ │ │ │
│ │ │ │ │ │
└───────────────────┘ └───────────────────┘ └───────────────────┘
▲ │
│ │
│ ▼
┌───────────────────┐ ┌───────────────────┐
│ │ │ │
│ Success Dialog + │◄─────────────────────────────│ Database │
│ Toast Notification│ │ │
│ │ │ │
└───────────────────┘ └───────────────────┘
```
### Security Considerations
The reset functionality requires special attention to security:
1. **Authentication**: Only authenticated users can access the reset endpoint
2. **Authorization**: Users must have permission to modify the specific project
3. **Confirmation**: A double confirmation pattern prevents accidental resets
4. **Validation**: Server-side validation ensures the projectId is valid
5. **Audit Logging**: The action should be logged for audit purposes
### Error Handling
The implementation includes comprehensive error handling:
1. **UI Error States**: Display appropriate error messages if the reset fails
2. **API Error Responses**: Return structured error responses from the API
3. **Recovery Mechanisms**: Provide guidance for users if errors occur
4. **Validation Errors**: Handle invalid inputs gracefully
## Tasks Breakdown
### Backend Implementation
#### API Endpoint Creation
- [ ] 1. Create a new API route handler file at `app/api/projects/[projectId]/reset/route.ts`
- [ ] 2. Implement the DELETE method handler that validates the request and calls the reset library function
- [ ] 3. Add proper error handling and response formatting
- [ ] 4. Add authentication check using Next Auth
#### Library Functions
- [ ] 5. Create a new library file `lib/db/projects/reset.ts` for project reset functionality
- [ ] 6. Implement function to delete all documents associated with a project
- [ ] 7. Implement function to delete all tasks associated with a project
- [ ] 8. Implement function to delete all characterizations associated with a project
- [ ] 9. Implement function to delete all events associated with a project
- [ ] 10. Implement function to delete all workflows associated with a project
- [ ] 11. Implement function to delete all agents associated with a project
- [ ] 12. Implement function to delete all chats and messages associated with a project
- [ ] 13. Implement function to delete all instructions associated with a project
- [ ] 14. Implement function to set `tasksImported` to false on the project
- [ ] 15. Create a main reset function that orchestrates all the deletion operations in a transaction
### Frontend Implementation
#### UI Components
- [ ] 16. Add a "Reset Project" button to the Project Settings component in `components/projects/project-settings-panel.tsx`
- [ ] 17. Create a confirmation dialog component for the reset action
- [ ] 18. Add success notification using the toast system
- [ ] 19. Implement loading state for the reset button during the operation
#### API Integration
- [ ] 20. Create a reset project API client function in `lib/db/projects/queries.ts`
- [ ] 21. Connect the reset button to the API client function
- [ ] 22. Handle API responses and errors in the UI
### Testing
- [ ] 23. Create API route test file `test/api/projects/reset.test.ts`
- [ ] 24. Write test cases for successful project reset
- [ ] 25. Write test cases for unauthorized access attempts
- [ ] 26. Write test cases for invalid project IDs
- [ ] 27. Create UI test file `test/components/projects/reset-project.test.tsx`
- [ ] 28. Write test for the Reset Project button rendering
- [ ] 29. Write test for confirmation dialog appearance and interaction
- [ ] 30. Write test for success notification
- [ ] 31. Write test for API client function in isolation
### Documentation
- [ ] 32. Update API documentation to include the new reset endpoint
- [ ] 33. Document the reset functionality in the project README or internal documentation
## Detailed Implementation Specifications
### Backend Implementation Details
#### API Endpoint
```typescript
// app/api/projects/[projectId]/reset/route.ts
import { auth } from '@/app/(auth)/auth';
import { resetProject } from '@/lib/db/projects/reset';
import { NextRequest, NextResponse } from 'next/server';
/**
* Handler for resetting a project.
* Deletes all associated data and resets the project state.
*
* @param request The incoming request
* @param params Object containing route parameters
* @returns NextResponse with status and message
*/
export async function DELETE(
request: NextRequest,
{ params }: { params: { projectId: string } }
) {
// Authentication check
const session = await auth();
if (!session || !session.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { projectId } = params;
if (!projectId) {
return NextResponse.json(
{ error: 'Project ID is required' },
{ status: 400 }
);
}
try {
// Call the reset library function
await resetProject(projectId);
return NextResponse.json(
{ message: 'Project reset successfully' },
{ status: 200 }
);
} catch (error) {
console.error('Error resetting project:', error);
return NextResponse.json(
{ error: 'Failed to reset project' },
{ status: 500 }
);
}
}
```
#### Library Functions
```typescript
// lib/db/projects/reset.ts
import { db } from '@/lib/db';
import { and, eq } from 'drizzle-orm';
import { documents, projects, tasks, characterizations, events, workflows, agents, chats, messages, instructions } from '@/lib/db/schema';
/**
* Resets a project by deleting all associated data and setting tasksImported to false.
* This is a destructive operation that cannot be undone.
*
* @param projectId The ID of the project to reset
* @returns Promise that resolves when reset is complete
*/
export async function resetProject(projectId: string): Promise<void> {
// Execute all operations in a transaction to ensure consistency
return db.transaction(async (tx) => {
// Delete all documents
await tx.delete(documents).where(eq(documents.projectId, projectId));
// Delete all tasks
await tx.delete(tasks).where(eq(tasks.projectId, projectId));
// Delete all characterizations
await tx.delete(characterizations).where(eq(characterizations.projectId, projectId));
// Delete all events
await tx.delete(events).where(eq(events.projectId, projectId));
// Delete all workflows
await tx.delete(workflows).where(eq(workflows.projectId, projectId));
// Delete all agents
await tx.delete(agents).where(eq(agents.projectId, projectId));
// Delete all chats and messages
// First, get all chat IDs for this project
const projectChats = await tx
.select({ id: chats.id })
.from(chats)
.where(eq(chats.projectId, projectId));
// Delete messages for these chats
for (const chat of projectChats) {
await tx.delete(messages).where(eq(messages.chatId, chat.id));
}
// Delete the chats themselves
await tx.delete(chats).where(eq(chats.projectId, projectId));
// Delete all instructions
await tx.delete(instructions).where(eq(instructions.projectId, projectId));
// Reset the tasksImported flag on the project
await tx
.update(projects)
.set({ tasksImported: false })
.where(eq(projects.id, projectId));
});
}
```
```typescript
// lib/db/projects/queries.ts (addition to existing file)
/**
* Reset a project by deleting all associated data and setting tasksImported to false.
*
* @param projectId - The ID of the project to reset
* @returns Promise that resolves when the project has been reset
*/
export async function resetProjectData(projectId: string): Promise<void> {
const response = await fetch(`/api/projects/${projectId}/reset`, {
method: 'DELETE',
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Failed to reset project');
}
}
```
### Frontend Implementation Details
#### Reset Button in Project Settings
```typescript
// components/projects/project-settings-panel.tsx (addition to existing component)
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { Button } from '@/components/ui/button';
import { ConfirmationDialog } from '@/components/ui/confirmation-dialog';
import { useToast } from '@/hooks/use-toast';
import { resetProjectData } from '@/lib/db/projects/queries';
// Add to existing component
const [isResetDialogOpen, setIsResetDialogOpen] = useState(false);
const [isResetting, setIsResetting] = useState(false);
const [resetSuccess, setResetSuccess] = useState(false);
const router = useRouter();
const { toast } = useToast();
const handleResetProject = async () => {
setIsResetting(true);
try {
await resetProjectData(project.id);
setIsResetting(false);
setResetSuccess(true);
toast({
title: 'Project reset successfully',
description: 'All project data has been deleted.',
variant: 'default',
});
} catch (error) {
setIsResetting(false);
toast({
title: 'Failed to reset project',
description: error instanceof Error ? error.message : 'An error occurred',
variant: 'destructive',
});
}
};
// Add this to the JSX in the component's return statement
<div className="border-t border-border pt-4 mt-4">
<h3 className="text-sm font-medium mb-4">Danger Zone</h3>
<div className="rounded border border-destructive p-4">
<div className="flex flex-col gap-2">
<h4 className="font-medium text-destructive">Reset Project</h4>
<p className="text-sm text-muted-foreground">
This will delete all documents, tasks, and other data associated with this project.
This action cannot be undone.
</p>
<Button
variant="destructive"
className="mt-2 w-fit"
onClick={() => setIsResetDialogOpen(true)}
>
Reset Project
</Button>
</div>
</div>
</div>
<ConfirmationDialog
open={isResetDialogOpen}
onOpenChange={setIsResetDialogOpen}
title="Reset Project"
description="Are you sure you want to reset this project? This will delete all tasks, documents, characterizations, and other data. This action cannot be undone."
confirmText="Reset Project"
cancelText="Cancel"
destructive
onConfirm={handleResetProject}
loading={isResetting}
/>
<ConfirmationDialog
open={resetSuccess}
onOpenChange={setResetSuccess}
title="Project Reset Successfully"
description="Your project has been reset. All tasks, documents, and other data have been deleted."
confirmText="Go to Project"
showCancel={false}
onConfirm={() => {
setResetSuccess(false);
router.push(`/app/projects/${project.id}`);
router.refresh();
}}
/>
```
### Test Implementation Details
```typescript
// test/api/projects/reset.test.ts
import { DELETE } from '@/app/api/projects/[projectId]/reset/route';
import { db } from '@/lib/db';
import { projects, documents, tasks, characterizations, events, workflows, agents, chats, messages, instructions } from '@/lib/db/schema';
import { createMocks } from 'node-mocks-http';
import { v4 as uuidv4 } from 'uuid';
import { eq } from 'drizzle-orm';
jest.mock('@/app/(auth)/auth', () => ({
auth: jest.fn(() => Promise.resolve({
user: { id: 'test-user-id', email: 'test@example.com' }
}))
}));
describe('Project Reset API', () => {
let projectId: string;
// Create test data before each test
beforeEach(async () => {
// Create a test project
projectId = uuidv4();
await db.insert(projects).values({
id: projectId,
name: 'Test Project',
description: 'Test Description',
userId: 'test-user-id',
tasksImported: true,
createdAt: new Date(),
updatedAt: new Date(),
});
// Create test documents, tasks, etc. for this project
await db.insert(documents).values({
id: uuidv4(),
projectId: projectId,
title: 'Test Document',
content: 'Test Content',
type: 'note',
createdAt: new Date(),
updatedAt: new Date(),
});
await db.insert(tasks).values({
id: uuidv4(),
projectId: projectId,
title: 'Test Task',
description: 'Test Description',
status: 'open',
createdAt: new Date(),
updatedAt: new Date(),
});
// Add more test data as needed
});
// Clean up after each test
afterEach(async () => {
// Clean up all test data
await db.delete(documents).where(eq(documents.projectId, projectId));
await db.delete(tasks).where(eq(tasks.projectId, projectId));
await db.delete(projects).where(eq(projects.id, projectId));
// Clean up other tables as needed
});
it('should reset a project successfully', async () => {
// Mock the request
const { req, res } = createMocks({
method: 'DELETE',
});
// Call the API route handler
await DELETE(req, { params: { projectId } });
// Check if all associated data was deleted
const projectDocs = await db.select().from(documents).where(eq(documents.projectId, projectId));
expect(projectDocs.length).toBe(0);
const projectTasks = await db.select().from(tasks).where(eq(tasks.projectId, projectId));
expect(projectTasks.length).toBe(0);
// Check if project still exists but tasksImported is set to false
const updatedProject = await db.select().from(projects).where(eq(projects.id, projectId)).limit(1);
expect(updatedProject.length).toBe(1);
expect(updatedProject[0].tasksImported).toBe(false);
});
it('should return 400 for missing project ID', async () => {
// Mock the request
const { req, res } = createMocks({
method: 'DELETE',
});
// Call the API route handler with empty params
const result = await DELETE(req, { params: { projectId: '' } });
const data = await result.json();
expect(result.status).toBe(400);
expect(data.error).toBe('Project ID is required');
});
// More tests for other cases...
});
```
```typescript
// test/components/projects/reset-project.test.tsx
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { ProjectSettingsPanel } from '@/components/projects/project-settings-panel';
import { resetProjectData } from '@/lib/db/projects/queries';
import { useRouter } from 'next/navigation';
// Mock the dependencies
jest.mock('next/navigation', () => ({
useRouter: jest.fn(),
}));
jest.mock('@/hooks/use-toast', () => ({
useToast: () => ({
toast: jest.fn(),
}),
}));
jest.mock('@/lib/db/projects/queries', () => ({
resetProjectData: jest.fn(),
}));
describe('Project Reset Button', () => {
const mockProject = {
id: 'test-project-id',
name: 'Test Project',
description: 'Test Description',
tasksImported: true,
};
const mockRouter = {
push: jest.fn(),
refresh: jest.fn(),
};
beforeEach(() => {
jest.clearAllMocks();
(useRouter as jest.Mock).mockReturnValue(mockRouter);
});
it('should render the reset button in the danger zone', () => {
render(<ProjectSettingsPanel project={mockProject} />);
expect(screen.getByText('Reset Project')).toBeInTheDocument();
expect(screen.getByText(/This will delete all documents, tasks, and other data/)).toBeInTheDocument();
});
it('should open confirmation dialog when reset button is clicked', async () => {
render(<ProjectSettingsPanel project={mockProject} />);
const resetButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(resetButton);
expect(screen.getByText('Are you sure you want to reset this project?')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Reset Project' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
});
it('should call reset API when confirmed', async () => {
(resetProjectData as jest.Mock).mockResolvedValue(undefined);
render(<ProjectSettingsPanel project={mockProject} />);
// Click the reset button
const resetButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(resetButton);
// Click the confirm button in the dialog
const confirmButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(confirmButton);
// Check if API was called
expect(resetProjectData).toHaveBeenCalledWith(mockProject.id);
});
it('should show success dialog after reset', async () => {
(resetProjectData as jest.Mock).mockResolvedValue(undefined);
render(<ProjectSettingsPanel project={mockProject} />);
// Click the reset button
const resetButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(resetButton);
// Click the confirm button in the dialog
const confirmButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(confirmButton);
// Wait for the success dialog to appear
await waitFor(() => {
expect(screen.getByText('Project Reset Successfully')).toBeInTheDocument();
});
// Click the "Go to Project" button
const goToProjectButton = screen.getByRole('button', { name: 'Go to Project' });
await userEvent.click(goToProjectButton);
// Verify navigation
expect(mockRouter.push).toHaveBeenCalledWith(`/app/projects/${mockProject.id}`);
expect(mockRouter.refresh).toHaveBeenCalled();
});
it('should handle API errors', async () => {
(resetProjectData as jest.Mock).mockRejectedValue(new Error('API error'));
render(<ProjectSettingsPanel project={mockProject} />);
// Click the reset button
const resetButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(resetButton);
// Click the confirm button in the dialog
const confirmButton = screen.getByRole('button', { name: 'Reset Project' });
await userEvent.click(confirmButton);
// Verify the toast was called (implementation depends on your toast setup)
// You could check for error elements or mock the toast function and verify it's called
});
});
```
## Required Files for Implementation
To implement this feature, the following files will be needed:
1. **New Files:**
- `app/api/projects/[projectId]/reset/route.ts`
- `lib/db/projects/reset.ts`
- `test/api/projects/reset.test.ts`
- `test/components/projects/reset-project.test.tsx`
2. **Files to Modify:**
- `components/projects/project-settings-panel.tsx`
- `lib/db/projects/queries.ts`
3. **Reference Files:**
- `lib/db/schema.ts`
- `components/ui/confirmation-dialog.tsx`
- `components/ui/button.tsx`
- `hooks/use-toast.ts`
- `app/(auth)/auth.ts`
This implementation plan provides a comprehensive guide for adding the reset functionality to the Project Details page, ensuring all required components, API endpoints, and tests are properly specified.
</plan>
Here are some requested instructions from the user. Follow these if possible, but do not do anything contrary to
your main instructions above:
<user-requested-instructions>
The repo consists of a Next JS 15 app in /app and a NPM JS CLI tool in /cli. The Next JS app is the SaaS has an API (see /app/api). The CLI tool integrates closely with the Next JS app (principally via its API), but is a separate codebase, with no code-sharing between the two.
When writing tests, do not import from jest/globals, they are already present for you.
When writing route.test.ts files (to test the API endpoints), do not mock out the database, instead create the data needed for the test via the schema.ts models in a beforeEach or beforeAll function, then surgically delete the data again in an afterAll/afterEach.
We use jest for coding - do not use vitest.
We use the toast hook for UI notifications: `import { useToast } from '@/hooks/use-toast';`
Always specify the use of the App Router pattern, not Page Router in Next JS.
Look at lib/db/schema.ts for the full data model.
We use drizzle for the ORM, make sure you do too and call it correctly.
The Next JS application has the marketing pages for the website (inside the app/(marketing) directory), and the SaaS app pages, which are inside the app/app directory. Most of the time we are working inside app/app
When working on the UI, use the ConfirmationDialog component from confirmation-dialog.tsx in place of document.confirm() when asking for user confirmation.
Use ShadCN components whenever possible.
Run pnpm lint:fix when you are done to make sure you have not introduced any lint errors.
You can run the UI tests using `pnpm test:ui` if you modified any UI or APIs.
When writing tests, do not import from jest/globals, they are already present for you.
When writing route.test.ts files (to test the API endpoints), do not mock out the database, instead create the data needed for the test via the schema.ts models in a beforeEach or beforeAll function, then surgically delete the data again in an afterAll/afterEach.
We use jest for coding - do not use vitest.
We use Next Auth for authentication, imported like this: `import { auth } from '@/app/(auth)/auth';`
We use the toast hook for UI notifications: `import { useToast } from '@/hooks/use-toast';`
</user-requested-instructions>
</data>
Please get started!
How does Task Demon know so much about my project?
Task Demon performs a one-time Characterization of your project when you first set it up. This process analyzes your codebase structure, dependencies, coding patterns, and architecture, creating a comprehensive understanding that enables all of Task Demon's powerful features.
This characterization is stored securely and used to generate detailed prompts for every task, without requiring re-analysis each time. You can update the characterization manually whenever your project undergoes significant changes.
Under the Hood
How Task Demon creates comprehensive implementation prompts from simple requests
Background Context Document
Generated during triage using Task Demon's one-time project characterization data. This document contains key information about the project structure, existing components, and patterns.
# Task Demon: Add Reset Button to Project Details Page
## Project Overview
**Project Name:** Task Demon
**Project ID:** 2d1b9dd6-a737-4b43-9c2a-6f6323908cb5
**Description:** Task Demon is a chatbot-centric SaaS application designed to automate software development workflows. It acts as an AI-powered task management system that creates and maintains tickets for work that needs to be done. The platform includes specialized AI agents that run on customer devices to automatically triage, plan, and implement work on git repositories. Task Demon integrates deeply with GitHub, providing a seamless experience for managing development tasks.
## Task Details
**Task ID:** eecc9da4-ae5e-4084-84b3-72a6ccbd817f
**Task Name:** Add Reset Button to Project Details Page
**Task Description:** Implement a button on the Project Details page that allows users to reset the project. This button should trigger a new API endpoint that calls a library function to delete all documents, tasks, characterizations, events, workflows, agents, chats, messages, and instructions for the project. Additionally, it should set `tasksImported` to false on the project. The reset option should be accessible via a button in the Project Settings page, which opens a confirmation modal to verify the action due to its destructive nature. After the reset is complete, the modal should inform the user of the success and provide a button to 'Go to Project'.
## Project Technical Details
### Technologies Used
- Next.js App Router for page routing
- React for UI components
- TypeScript for type safety
- ShadCN UI for UI components and styling
- Tailwind CSS for styling
- Drizzle ORM for database access
- Pusher for real-time updates
### Code Conventions
- TypeScript: Prefer interfaces over types, no React.FC
- Naming: PascalCase for components, camelCase for utilities
- Directories: Lowercase with dashes
- Formatting: 2-space indentation, single quotes, semicolons
- Testing: Jest for unit tests
## Relevant Project Structure
```
app/
api/
projects/
[projectId]/
reset/ <-- New API endpoint to be created here
route.ts
app/
projects/
[projectId]/
page.tsx
layout.tsx
guard.tsx
components/
projects/
project-settings.tsx <-- Reset button to be added here
project-settings-panel.tsx
confirmation-dialog.tsx <-- Can be used for reset confirmation
lib/
db/
projects/
reset.ts <-- New library function to be created here
queries.ts
test/
api/
projects/
reset.test.ts <-- Tests to be added here
components/
projects/
project-settings.test.tsx
```
## Relevant Information from Project Documents
### Project Details Page Characterization
- **Core Components:**
- **Server Components:** Located in `app/app/projects/[projectId]`, including:
- `page.tsx`: Main server component that fetches and renders project data.
- `layout.tsx`: Provides ProjectProvider context to child components.
- **Client Components:** Primarily in `components/projects/`, structured as:
- Project header (title, description).
- Settings panel (preferences, GitHub integration).
- Characterization summary section.
- Task list with filtering capabilities.
- Project chat interface.
- Activity feed with real-time updates.
- Documents section organized by type.
- Project agents section.
- **State Management:**
- `ProjectProvider`: Provides project data and UI preferences.
- `use-project-context.tsx`: Context hook managing project state.
- Custom hooks for real-time data synchronization:
- `use-project-events.ts`: Manages project activity with pagination.
- `use-project-events-swr.ts`: Handles real-time updates via Pusher.
- **Data Flow:**
- **Initial Load:** Server fetches project data, tasks, and characterization status.
- **Real-time Updates:** Pusher channels provide WebSocket-based notifications.
- **User Interactions:** Edit project metadata, start/view characterization, filter and view tasks, chat with project AI, monitor activity feed.
### API Documentation
- **Projects API:**
- `/api/projects/:projectId`: Get project details.
- `/api/projects/:projectId/tasks`: List project tasks.
- `/api/projects/:projectId/characterization`: Get project characterization.
- **New Endpoint Required:** A new API endpoint will be needed to handle the reset functionality, which will delete all related data and reset `tasksImported`.
### Database Schema
The reset operation will need to delete records from the following tables:
- documents: WHERE projectId = ?
- tasks: WHERE projectId = ?
- characterizations: WHERE projectId = ?
- events: WHERE projectId = ?
- workflows: WHERE projectId = ?
- agents: WHERE projectId = ?
- chats: WHERE projectId = ?
- messages: WHERE chat IN (SELECT id FROM chats WHERE projectId = ?)
- instructions: WHERE projectId = ?
The project record itself should be updated to set tasksImported = false.
### Confirmation Dialog Pattern
The application uses the following pattern for confirmation dialogs:
```typescript
<ConfirmationDialog
isOpen={isConfirmationOpen}
onClose={() => setIsConfirmationOpen(false)}
onConfirm={handleConfirmAction}
title="Confirmation Required"
description="Are you sure you want to perform this action? This cannot be undone."
confirmText="Confirm"
cancelText="Cancel"
/>
```
### Toast Notification Pattern
The application uses the following pattern for success notifications:
```typescript
import { useToast } from "@/hooks/use-toast";
const { toast } = useToast();
// Show success toast
toast({
title: "Success",
description: "Operation completed successfully",
variant: "success",
});
```
Implementation Plan Document
Based on the background context, Task Demon creates a detailed implementation plan that breaks down the work into specific tasks with clear steps.
# Implementation Plan: Add Reset Button to Project Details Page
## Overview
Based on the analysis of the codebase and requirements, I've developed a detailed implementation plan for adding the reset project functionality. This plan follows the existing architectural patterns and coding conventions of the Task Demon application.
## Step 1: Create Backend Reset Functionality
First, we'll implement the core data functions that will handle the actual reset operation.
### 1.1 Create Reset Project Library Function
**File:** `lib/db/projects/reset.ts`
This function will:
1. Delete all associated records (documents, tasks, characterizations, events, workflows, agents, chats, messages, instructions)
2. Update the project record to set `tasksImported` to false
3. Return the updated project record
```typescript
import { db } from '@/lib/db';
import { projects, documents, tasks, characterizations, events, workflows, agents, chats, messages, instructions } from '@/lib/db/schema';
import { and, eq } from 'drizzle-orm';
import { Project } from '@/lib/db/types';
/**
* Resets a project by deleting all associated data and setting tasksImported to false
*
* @param projectId The ID of the project to reset
* @returns The updated project record
* @throws If the project doesn't exist or the reset operation fails
*/
export async function resetProject(projectId: string): Promise<Project> {
return db.transaction(async (tx) => {
// First, check if the project exists
const existingProject = await tx.query.projects.findFirst({
where: eq(projects.id, projectId),
});
if (!existingProject) {
throw new Error(`Project with ID ${projectId} not found`);
}
// Delete all associated data
await tx.delete(documents).where(eq(documents.projectId, projectId));
await tx.delete(tasks).where(eq(tasks.projectId, projectId));
await tx.delete(characterizations).where(eq(characterizations.projectId, projectId));
await tx.delete(events).where(eq(events.projectId, projectId));
await tx.delete(workflows).where(eq(workflows.projectId, projectId));
await tx.delete(agents).where(eq(agents.projectId, projectId));
// Get all chat IDs for this project
const projectChats = await tx.query.chats.findMany({
where: eq(chats.projectId, projectId),
columns: {
id: true,
},
});
// Delete all messages from these chats
for (const chat of projectChats) {
await tx.delete(messages).where(eq(messages.chatId, chat.id));
}
// Now delete the chats
await tx.delete(chats).where(eq(chats.projectId, projectId));
// Delete instructions
await tx.delete(instructions).where(eq(instructions.projectId, projectId));
// Update the project to set tasksImported to false
await tx.update(projects)
.set({ tasksImported: false })
.where(eq(projects.id, projectId));
// Return the updated project
const updatedProject = await tx.query.projects.findFirst({
where: eq(projects.id, projectId),
});
if (!updatedProject) {
throw new Error(`Failed to fetch updated project with ID ${projectId}`);
}
return updatedProject;
});
}
```
### 1.2 Create Reset API Endpoint
**File:** `app/api/projects/[projectId]/reset/route.ts`
This endpoint will:
1. Verify that the user is authenticated and authorized to reset the project
2. Call the `resetProject` function to perform the reset
3. Return a success response with the updated project data
```typescript
import { NextResponse } from 'next/server';
import { resetProject } from '@/lib/db/projects/reset';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/app/(auth)/auth.config';
import { getUserProject } from '@/lib/db/projects/queries';
export async function POST(
request: Request,
{ params }: { params: { projectId: string } }
) {
try {
const session = await getServerSession(authOptions);
if (!session?.user) {
return NextResponse.json(
{ error: 'Unauthorized' },
{ status: 401 }
);
}
const { projectId } = params;
// Check if the user has access to this project
const userProject = await getUserProject(projectId, session.user.id);
if (!userProject) {
return NextResponse.json(
{ error: 'Project not found or you don\'t have access to it' },
{ status: 404 }
);
}
// Reset the project
const updatedProject = await resetProject(projectId);
return NextResponse.json({
message: 'Project reset successfully',
project: updatedProject
});
} catch (error) {
console.error('Error resetting project:', error);
return NextResponse.json(
{ error: 'Failed to reset project' },
{ status: 500 }
);
}
}
```
Generated Commit Message
Task Demon generates professional, descriptive commit messages based on the implemented changes.
Add reset project functionality in settings panel
- Add Reset Project button in the Project Settings panel's "Danger Zone" section
- Implement resetProject database function to delete all associated project data
- Create new API endpoint at /api/projects/[projectId]/reset for handling reset requests
- Add confirmation dialog with clear warning about data loss
- Show success notification after reset completion
- Provide "Go to Project" button after successful reset
- Add comprehensive tests for the API endpoint and UI components
This implementation allows users to completely reset their projects to initial state
while maintaining proper authorization and data integrity throughout the process.
Generated Pull Request Description
Task Demon creates detailed pull request descriptions that document the changes, testing approach, and security considerations.
## Add Project Reset Functionality This PR adds the ability for users to reset a project to its initial state by deleting all associated data. This feature is useful for users who want to start fresh with a project after testing or experimenting. ### Changes - Add a new "Danger Zone" section in the Project Settings panel with a Reset Project button - Create a new API endpoint at `/api/projects/[projectId]/reset` for handling reset requests - Implement a database function in `lib/db/projects/reset.ts` to: - Delete all documents, tasks, characterizations, events, workflows, agents, chats, and messages - Set `tasksImported` to false on the project record - Add a confirmation dialog to verify the user's intention before reset - Show success notification after reset completion - Provide a "Go to Project" button after successful reset - Add comprehensive tests for the API endpoint and UI components ### Screenshots [Screenshot of the Project Settings panel with Reset button] [Screenshot of the confirmation dialog] [Screenshot of the success notification] ### Testing - Tested with multiple projects with varying amounts of data - Verified all associated data is properly deleted - Ensured proper authorization checks - Tested error handling for various edge cases ### Security Considerations - Only authorized users can reset their own projects - Clear warning about the destructive nature of this action - All operations performed in a transaction to prevent partial data deletion
Ready to transform your development process?
Experience the power of AI-driven task management with TaskDemon.AI. Create detailed plans and implementation guides for your own projects.