Common Tasks Reference
Quick reference for frequently performed development tasks with complete file lists.
Task 1: Add New Field to Existing Model
Example: Add estimated_time field to Task
Files to Modify
-
Create migration
npm run migration:create -- --name add-estimated-time-to-tasksEdit
/backend/migrations/YYYYMMDDHHMMSS-add-estimated-time-to-tasks.js -
Update model
/backend/models/task.js- Add field definition
-
Update serializer
/backend/modules/tasks/core/serializers.js- Add toserializeTask()
-
Update builder
/backend/modules/tasks/core/builders.js- Add tobuildTaskAttributes()
-
Add validation (if needed)
/backend/modules/tasks/routes.js- Add validation logic
-
Update API docs
/backend/config/swagger.js- Update Task schema
-
Update frontend types
/frontend/entities/Task.ts- Add to interface (if exists)
-
Update UI
/frontend/components/Task/TaskForm.tsx- Add input field/frontend/components/Task/TaskItem.tsx- Display field (if needed)
-
Add tests
/backend/tests/integration/tasks/tasks.test.js- Test CRUD with new field
Commands
npm run migration:create -- --name add-estimated-time-to-tasks
# Edit migration file
npm run migration:run
npm run backend:test
npm run lint:fix
npm run format:fix
Task 2: Create New Backend Module
Example: Create "labels" module
Steps
-
Create directory structure
mkdir -p /Users/chris/c0deLab/ProjectLand/tududi/backend/modules/labels -
Create files
/backend/modules/labels/routes.js- Express routes/backend/modules/labels/repository.js- Data access
-
Create model
/backend/models/label.js- Sequelize model- Update
/backend/models/index.js- Add associations
-
Create migration
npm run migration:create -- --name create-labels-table- Edit
/backend/migrations/YYYYMMDDHHMMSS-create-labels-table.js
- Edit
-
Register routes
- Edit
/backend/app.js:
app.use('/api/v1', require('./modules/labels/routes'));
app.use('/api', require('./modules/labels/routes')); - Edit
-
Add Swagger docs
- Edit
/backend/config/swagger.js- Add Label schema
- Edit
-
Write tests
- Create
/backend/tests/integration/labels/labels.test.js
- Create
-
Frontend integration (optional)
/frontend/entities/Label.ts- TypeScript interface/frontend/utils/labelsService.ts- API client/frontend/components/Label/- Components
Commands
npm run migration:create -- --name create-labels-table
npm run migration:run
npm run backend:test
Task 3: Add New React Component
Example: Create TaskPriorityBadge component
Files to Create
-
Component file
/frontend/components/Task/TaskPriorityBadge.tsx
-
Test file (optional)
/frontend/components/Task/__tests__/TaskPriorityBadge.test.tsx
-
Import in parent component
/frontend/components/Task/TaskItem.tsx- Import and use
Example Component
// TaskPriorityBadge.tsx
import React from 'react';
interface TaskPriorityBadgeProps {
priority: number;
}
export const TaskPriorityBadge: React.FC<TaskPriorityBadgeProps> = ({ priority }) => {
const configs = {
0: { label: 'Low', className: 'bg-gray-200 text-gray-800' },
1: { label: 'Medium', className: 'bg-yellow-200 text-yellow-800' },
2: { label: 'High', className: 'bg-red-200 text-red-800' }
};
const config = configs[priority] || configs[0];
return (
<span className={`px-2 py-1 rounded text-xs font-semibold ${config.className}`}>
{config.label}
</span>
);
};
Commands
npm run frontend:test
npm run lint:fix
Task 4: Update Database Schema
Example: Add index to Tasks table
Steps
-
Create migration
npm run migration:create -- --name add-index-to-tasks-due-date -
Edit migration file
/backend/migrations/YYYYMMDDHHMMSS-add-index-to-tasks-due-date.jsasync up(queryInterface, Sequelize) {
await queryInterface.addIndex('Tasks', ['due_date'], {
name: 'tasks_due_date_index'
});
}
async down(queryInterface, Sequelize) {
await queryInterface.removeIndex('Tasks', 'tasks_due_date_index');
} -
Test migration
npm run migration:run
npm run migration:undo # Test rollback
npm run migration:run # Re-apply -
Update model (optional)
- Index definition can be in migration only, or also in model
Commands
npm run migration:create -- --name add-index-to-tasks-due-date
npm run migration:run
npm run backend:test
Task 5: Fix a Bug (TDD Workflow)
Example: Fix bug where completed tasks show in Today view
Steps
-
Write failing test first
Edit
/backend/tests/integration/tasks/tasks.test.js:it('should not return completed tasks in Today view', async () => {
// Arrange - Create completed task
await Task.create({
name: 'Completed Task',
status: 2,
due_date: new Date().toISOString().split('T')[0],
user_id: user.id
});
// Act
const response = await request(app)
.get('/api/v1/tasks/today')
.set('Cookie', authCookie);
// Assert
expect(response.status).toBe(200);
const completedTasks = response.body.filter(t => t.status === 2);
expect(completedTasks.length).toBe(0);
}); -
Run test - verify it fails
npm run backend:test -
Fix the bug
Edit
/backend/modules/tasks/queries/query-builders.jsor/backend/modules/tasks/operations/list.js:// Add status filter to Today query
where.status = { [Op.ne]: 2 }; // Exclude completed -
Run test - verify it passes
npm run backend:test -
Run all checks
npm run pre-push -
Commit
git add .
git commit -m "Fix completed tasks appearing in Today view (#123)
- Add status filter to Today query
- Add test to prevent regression"
Task 6: Add Translation Key
Backend Translations
Backend typically doesn't use translations (API responses in English).
Frontend Translations
-
Add key to English source
Edit
/public/locales/en/translation.json:{
"task": {
"estimatedTime": "Estimated Time",
"estimatedTimePlaceholder": "Enter time in minutes",
"estimatedTimeUnit": "minutes"
}
} -
Use in component
import { useTranslation } from 'react-i18next';
const TaskForm = () => {
const { t } = useTranslation();
return (
<div>
<label>{t('task.estimatedTime')}</label>
<input
type="number"
placeholder={t('task.estimatedTimePlaceholder')}
/>
<span>{t('task.estimatedTimeUnit')}</span>
</div>
);
}; -
Sync translations (if tool available)
npm run translations:sync
npm run translations:check
Task 7: Add API Endpoint Documentation
Update Swagger Schema
Edit /backend/config/swagger.js:
// Update existing schema
components: {
schemas: {
Task: {
type: 'object',
properties: {
id: { type: 'integer' },
uid: { type: 'string' },
name: { type: 'string' },
estimated_time: {
type: 'integer',
description: 'Estimated time in minutes',
nullable: true,
example: 30
}
}
}
}
}
Document New Endpoint with JSDoc
In /backend/modules/tasks/routes.js:
/**
* @swagger
* /api/v1/task/{id}/estimate:
* put:
* summary: Update task estimated time
* tags: [Tasks]
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* estimated_time:
* type: integer
* description: Time in minutes
* responses:
* 200:
* description: Task updated successfully
* content:
* application/json:
* schema:
* $ref: '#/components/schemas/Task'
* 404:
* description: Task not found
*/
router.put('/task/:id/estimate', async (req, res, next) => {
// Implementation
});
View Swagger Docs
- Start server:
npm run backend:dev - Login to app
- Visit: http://localhost:3002/api-docs
Task 8: Add Subtask to Task
Example: Add subtasks to a task
This is already implemented in tududi, but here's the pattern:
Files Involved
-
Migration
- Already exists:
parent_task_idfield in Tasks table
- Already exists:
-
Model
/backend/models/task.js- Self-referential association/backend/models/index.js- Define relationship:
Task.hasMany(Task, { as: 'Subtasks', foreignKey: 'parent_task_id' });
Task.belongsTo(Task, { as: 'ParentTask', foreignKey: 'parent_task_id' }); -
Backend operations
/backend/modules/tasks/operations/subtasks.js- Subtask CRUD
-
Frontend
/frontend/components/Task/SubtaskList.tsx- Display subtasks/frontend/components/Task/TaskDetails.tsx- Show subtasks
Task 9: Add Permission/Sharing to Resource
Example: Add sharing to a new resource type
Steps
-
Ensure Permission model supports resource type
Check
/backend/models/permission.js:resource_type: {
type: DataTypes.STRING,
allowNull: false,
// Should support your resource type
} -
Use
hasAccessmiddleware in routesconst { hasAccess } = require('../../middleware/authorize');
router.get('/myresource/:id',
hasAccess('ro', 'myresource', (req) => req.params.id),
async (req, res, next) => {
// Handler
}
); -
Implement sharing endpoints
See
/backend/modules/shares/for reference -
Frontend sharing UI
See
/frontend/components/Project/ProjectSharing.tsxfor reference
Task 10: Add Recurring Pattern to Task
Example: Add new recurrence type
Files to Check/Modify
-
Task model
/backend/models/task.js- Recurrence fields
-
Recurring task service
/backend/modules/tasks/recurringTaskService.js- Add new pattern logic
-
Task scheduler
/backend/modules/tasks/taskScheduler.js- Ensure cron job handles new pattern
-
Frontend
/frontend/components/Task/TaskForm.tsx- Add UI for new pattern
Task 11: Export Data (Backup)
Example: Create database backup
Already implemented in tududi:
# Via API (after login)
POST /api/v1/backup
# Returns JSON file with all user data
See /backend/modules/backup/ for implementation details.
Quick Command Reference
# Database
npm run db:init # Initialize database
npm run db:reset # Reset database
npm run migration:create -- --name # Create migration
npm run migration:run # Run migrations
npm run migration:undo # Rollback migration
# Development
npm start # Run both frontend + backend
npm run backend:dev # Backend only
npm run frontend:dev # Frontend only
# Testing
npm test # Backend tests
npm run frontend:test # Frontend tests
npm run test:ui # E2E tests
npm run test:coverage # Coverage report
# Code Quality
npm run lint # Check linting
npm run lint:fix # Fix linting
npm run format:fix # Format code
npm run pre-push # All checks
# Build
npm run build # Production build