Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
de18e52
setup & create task, category
maxn990 Aug 3, 2025
da5e6f7
fixed pr review comments
maxn990 Aug 5, 2025
20fd180
Merge pull request #13 from Code-4-Community/mn-1-2-create-task
amywng Aug 5, 2025
73da3ed
add label and migration to add tasks/labels tables
amywng Aug 6, 2025
270ea04
update datasource
maxn990 Aug 6, 2025
d728338
Merge pull request #14 from Code-4-Community/amy/create-label
amywng Aug 6, 2025
71338f1
finish setup
maxn990 Aug 8, 2025
9ba4ee5
Update example.env
maxn990 Aug 8, 2025
8f9f435
Merge pull request #16 from Code-4-Community/mn-15/setup-and-seeding
maxn990 Aug 8, 2025
16f1d6d
Create CreateTaskDTO
aaronashby Aug 10, 2025
9564ecf
Create post endpoint
aaronashby Aug 10, 2025
c51ac01
Merge branch 'main' into aa-3-create-task-route
aaronashby Aug 10, 2025
4ce5e12
Fixed db migration issues
aaronashby Aug 10, 2025
e5d2491
Final commit for the branch
dburkhart07 Aug 12, 2025
f358ad1
Created initally working endpoint. Still need to do some edge case ha…
dburkhart07 Aug 12, 2025
5e685d1
add npm run test
maxn990 Aug 12, 2025
c4399e8
Merge pull request #18 from Code-4-Community/mn-testing
maxn990 Aug 12, 2025
6532e66
Added testing
dburkhart07 Aug 12, 2025
232996c
Removed e2e testing
dburkhart07 Aug 12, 2025
e79d900
Completed unit tests
dburkhart07 Aug 12, 2025
82f2e26
Finished test updates
dburkhart07 Aug 12, 2025
51f5d51
Create CODEOWNERS
maxn990 Aug 12, 2025
a08684e
Merge pull request #19 from Code-4-Community/maxn990-patch-1
maxn990 Aug 12, 2025
4f52de0
Merged main into branch
dburkhart07 Aug 12, 2025
bb0a0a6
Completed testing
dburkhart07 Aug 12, 2025
468b224
Refactor task creation DTO and service logic
aaronashby Aug 12, 2025
19de9b9
Merge branch 'main' into aa-3-create-task-route
aaronashby Aug 12, 2025
0f5370a
Simplified task creation
aaronashby Aug 12, 2025
b196f0c
Added unit tests for controller
aaronashby Aug 13, 2025
331258d
Added unit tests for service
aaronashby Aug 14, 2025
8607013
Merge pull request #20 from Code-4-Community/7-move-task-route
dburkhart07 Aug 14, 2025
4b4b026
Resolved merge conflicts
dburkhart07 Aug 14, 2025
fdc030c
Merge pull request #17 from Code-4-Community/11-get-all-tasks
dburkhart07 Aug 14, 2025
f1dadd9
Merge branch 'main' into aa-3-create-task-route
aaronashby Aug 14, 2025
fefbc1a
Merge pull request #21 from Code-4-Community/aa-3-create-task-route
aaronashby Aug 14, 2025
b8618ad
Implemented PUT endpoint
aaronashby Aug 15, 2025
9719b48
Created controller unit tests
aaronashby Aug 15, 2025
ee5acff
Created service tests
aaronashby Aug 15, 2025
9bd5e02
create label endpoints + test
chnnick Aug 17, 2025
151659f
setup frontend tickets
maxn990 Aug 17, 2025
05d7ee4
Merge pull request #26 from Code-4-Community/mn-components
maxn990 Aug 17, 2025
955fedb
move to src
maxn990 Aug 17, 2025
7b27ff7
Merge pull request #27 from Code-4-Community/mn-components
maxn990 Aug 17, 2025
0d03f8a
changed label DTO 'title' field to match label entity 'name'
chnnick Aug 17, 2025
8d6403f
Final commit for initial dev work
dburkhart07 Aug 17, 2025
c6935f0
Made requested changes
dburkhart07 Aug 18, 2025
661e74c
implemented/tested delete_labels route
Ryaken-Nakamoto Aug 18, 2025
06975d5
Fixed changes
dburkhart07 Aug 18, 2025
0dd655b
Update update-task.dto.ts
aaronashby Aug 18, 2025
51c209f
Changed title-checking logic
aaronashby Aug 18, 2025
f008293
Update task.service.ts
aaronashby Aug 18, 2025
763bc37
Merge branch 'main' into aa-6-edit-task-route
aaronashby Aug 18, 2025
096b3cc
Merge pull request #29 from Code-4-Community/24-create-4-boxes
amywng Aug 18, 2025
273751d
Made requested changes
aaronashby Aug 18, 2025
342c4aa
Merge pull request #30 from Code-4-Community/aa-6-edit-task-route
amywng Aug 18, 2025
146a2bb
Create TaskCard.tsx
aaronashby Aug 19, 2025
9a5cb7c
Made container background white
aaronashby Aug 19, 2025
8fafe4e
made suggested edits
Ryaken-Nakamoto Aug 20, 2025
cf28e1d
Merge branch 'main' into remove_labels
Ryaken-Nakamoto Aug 20, 2025
7902b54
Made requested changes
aaronashby Aug 20, 2025
53aecdf
Merge pull request #31 from Code-4-Community/remove_labels
amywng Aug 20, 2025
39f43ef
Made requested changes and increased layout responsiveness
aaronashby Aug 20, 2025
1ba79c3
Merge pull request #32 from Code-4-Community/aa-25-create-task
amywng Aug 20, 2025
5575a44
mockReset + explicit error message added to tests
chnnick Aug 21, 2025
7a8e5be
implemented/tested ticket
Ryaken-Nakamoto Aug 22, 2025
cbd9ee8
Merge pull request #28 from Code-4-Community/8-label-route
amywng Aug 22, 2025
c5c91ce
made suggested edits
Ryaken-Nakamoto Aug 22, 2025
87ad3e2
Merge pull request #37 from Code-4-Community/add_labels
maxn990 Aug 22, 2025
196301a
fix lint (hopefully)
maxn990 Aug 24, 2025
f4fe168
Fixed linting issues
dburkhart07 Aug 24, 2025
8d15921
Final commit
dburkhart07 Aug 24, 2025
61c1957
Final commit
dburkhart07 Aug 24, 2025
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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @maxn990 @amywng
10 changes: 0 additions & 10 deletions apps/backend-e2e/src/apps/backend/apps/backend.spec.ts

This file was deleted.

9 changes: 7 additions & 2 deletions apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ import { TypeOrmModule } from '@nestjs/typeorm';

import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TaskModule } from './task/task.module';
import AppDataSource from './data-source';
import { TaskModule } from './task/task.module';
import { LabelModule } from './label/label.module';

@Module({
imports: [TypeOrmModule.forRoot(AppDataSource.options), TaskModule],
imports: [
TypeOrmModule.forRoot(AppDataSource.options),
TaskModule,
LabelModule,
],
controllers: [AppController],
providers: [AppService],
})
Expand Down
18 changes: 0 additions & 18 deletions apps/backend/src/auth/auth.controller.spec.ts

This file was deleted.

18 changes: 0 additions & 18 deletions apps/backend/src/auth/auth.service.spec.ts

This file was deleted.

3 changes: 2 additions & 1 deletion apps/backend/src/data-source.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DataSource } from 'typeorm';
import { PluralNamingStrategy } from './strategies/plural-naming.strategy';
import { Task } from './task/types/task.entity';
import { Label } from './label/types/label.entity';
import * as dotenv from 'dotenv';

dotenv.config();
Expand All @@ -12,7 +13,7 @@ const AppDataSource = new DataSource({
username: process.env.NX_DB_USERNAME,
password: process.env.NX_DB_PASSWORD,
database: process.env.NX_DB_DATABASE,
entities: [Task],
entities: [Task, Label],
migrations: ['apps/backend/src/migrations/*.js'],
// Setting synchronize: true shouldn't be used in production - otherwise you can lose production data
synchronize: false,
Expand Down
12 changes: 12 additions & 0 deletions apps/backend/src/label/dtos/create-label.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { IsString, IsHexColor } from 'class-validator';

export class CreateLabelDTO {
@IsString()
name: string;

@IsString()
description: string;

@IsHexColor()
color: string;
}
60 changes: 60 additions & 0 deletions apps/backend/src/label/label.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Test, TestingModule } from '@nestjs/testing';
import { LabelsController } from './label.controller';
import { LabelsService } from './label.service';
import { CreateLabelDTO } from './dtos/create-label.dto';
import { Label } from './types/label.entity';

// Mock implementation for LabelsService
export const mockLabelService: Partial<LabelsService> = {
createLabel: jest.fn((labelDto: CreateLabelDTO) =>
Promise.resolve(mockLabel),
),
};

export const mockLabelDto: CreateLabelDTO = {
name: 'Test Label',
description: 'Test Description',
color: '#000000',
};

export const mockLabel: Label = {
id: 1,
name: 'Test Label',
description: 'Test Description',
color: '#000000',
tasks: [],
};

describe('LabelController', () => {
let controller: LabelsController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [LabelsController],
providers: [
{
provide: LabelsService,
useValue: mockLabelService,
},
],
}).compile();

controller = module.get<LabelsController>(LabelsController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});

/* Test for create new label */
describe('POST /labels', () => {
it('should create a new label and return it', async () => {
jest.spyOn(mockLabelService, 'createLabel').mockResolvedValue(mockLabel);

const res = await controller.createLabel(mockLabelDto);

expect(res).toEqual(mockLabel);
expect(mockLabelService.createLabel).toHaveBeenCalledWith(mockLabelDto);
});
});
});
32 changes: 32 additions & 0 deletions apps/backend/src/label/label.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {
Controller,
Get,
Post,
Body,
Patch,
Param,
Delete,
Query,
} from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger';
import { LabelsService } from './label.service';
import { Label } from './types/label.entity';
import { CreateLabelDTO } from './dtos/create-label.dto';

@ApiTags('labels')
@Controller('labels')
export class LabelsController {
constructor(private readonly labelsService: LabelsService) {}

/** Creates a new label.
* @param LabelDto - The data transfer object containing label details.
* @returns The created label.
* @throws BadRequestException if the label name is not unique
* @throws BadRequestException if label name is not provided
* @throws BadRequestException if color is not provided or is not hexadecimal
*/
@Post('/label')
async createLabel(@Body() labelDto: CreateLabelDTO): Promise<Label> {
return this.labelsService.createLabel(labelDto);
}
}
13 changes: 13 additions & 0 deletions apps/backend/src/label/label.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Label } from './types/label.entity';
import { LabelsService } from './label.service';
import { LabelsController } from './label.controller';

@Module({
imports: [TypeOrmModule.forFeature([Label])],
providers: [LabelsService],
controllers: [LabelsController],
exports: [LabelsService],
})
export class LabelModule {}
97 changes: 97 additions & 0 deletions apps/backend/src/label/label.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { Test, TestingModule } from '@nestjs/testing';
import { mock } from 'jest-mock-extended';
import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Label } from './types/label.entity';
import { LabelsService } from './label.service';
import { mockLabel, mockLabelDto } from './label.controller.spec';
import { BadRequestException } from '@nestjs/common';

const mockLabelsRepository = mock<Repository<Label>>();

describe('LabelService', () => {
let service: LabelsService;

const mockValidCreateLabelDTO = {
name: 'Label 1',
description: 'Desc 1',
color: '#000000',
};

const mockInvalidCreateLabelDTO1 = {
name: '',
description: 'Desc 1',
color: '#000000',
};

const mockInvalidCreateLabelDTO2 = {
name: 'Label 2',
description: 'Desc 2',
color: '',
};

const mockInvalidCreateLabelDTO3 = {
name: 'Label 3',
description: 'Desc 3',
color: 'Hello',
};

beforeEach(async () => {
mockLabelsRepository.create.mockReset();
mockLabelsRepository.save.mockReset();
mockLabelsRepository.findOneBy.mockReset();
mockLabelsRepository.find.mockReset();

const module: TestingModule = await Test.createTestingModule({
providers: [
LabelsService,
{
provide: getRepositoryToken(Label),
useValue: mockLabelsRepository,
},
],
}).compile();

service = module.get<LabelsService>(LabelsService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});

describe('createLabel', () => {
it('should create a new label and return it', async () => {
// Mock the repository methods
mockLabelsRepository.create.mockReturnValue(mockLabel);
mockLabelsRepository.save.mockResolvedValue(mockLabel);

const label = await service.createLabel(mockValidCreateLabelDTO);

expect(label).toEqual(mockLabel);
});

it('should throw a BadRequestException when given null label name', async () => {
expect(async () => {
await service.createLabel(mockInvalidCreateLabelDTO1);
}).rejects.toThrow(
new BadRequestException("The 'name' field cannot be null"),
);
});

it('should throw a BadRequestException when given null label color', async () => {
expect(async () => {
await service.createLabel(mockInvalidCreateLabelDTO2);
}).rejects.toThrow(
new BadRequestException("The 'color' field cannot be null"),
);
});

it('should throw a BadRequestException when given invalid label color', async () => {
expect(async () => {
await service.createLabel(mockInvalidCreateLabelDTO3);
}).rejects.toThrow(
new BadRequestException("The 'color' field must be a valid hex color"),
);
});
});
});
34 changes: 34 additions & 0 deletions apps/backend/src/label/label.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Label } from './types/label.entity';
import { CreateLabelDTO } from './dtos/create-label.dto';
import { isHexColor } from 'class-validator';

@Injectable()
export class LabelsService {
constructor(
@InjectRepository(Label)
private labelRepository: Repository<Label>,
) {}

// Creates a new label
async createLabel(labelDto: CreateLabelDTO): Promise<Label> {
if (!labelDto.name) {
throw new BadRequestException("The 'name' field cannot be null");
}

if (!labelDto.color) {
throw new BadRequestException("The 'color' field cannot be null");
}

if (!isHexColor(labelDto.color)) {
throw new BadRequestException(
"The 'color' field must be a valid hex color",
);
}

const newLabel = this.labelRepository.create(labelDto);
return this.labelRepository.save(newLabel);
}
}
20 changes: 20 additions & 0 deletions apps/backend/src/label/types/label.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Column, Entity, PrimaryGeneratedColumn, ManyToMany } from 'typeorm';
import { Task } from '../../task/types/task.entity';

@Entity()
export class Label {
@PrimaryGeneratedColumn()
id: number;

@Column({ unique: true })
name: string;

@Column({ nullable: true })
description: string;

@Column()
color: string;

@ManyToMany(() => Task, (task) => task.labels)
tasks: Task[];
}
19 changes: 0 additions & 19 deletions apps/backend/src/migrations/1754254886189-add_task.ts

This file was deleted.

Loading
Loading