Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
141 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
9d41691
Created basic endpoint, to finish testing
chnnick Aug 16, 2025
e142a43
tests + minor changes to delete task object instead of id
chnnick Aug 17, 2025
99a538f
made the endpoint return promise of success and message response
chnnick Aug 17, 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
3f11fde
added header component
Ryaken-Nakamoto Aug 22, 2025
cbd9ee8
Merge pull request #28 from Code-4-Community/8-label-route
amywng Aug 22, 2025
475365f
updated constructor to take in first and last name
Ryaken-Nakamoto Aug 22, 2025
c5c91ce
made suggested edits
Ryaken-Nakamoto Aug 22, 2025
0e96fa2
made suggested edits pt2
Ryaken-Nakamoto Aug 22, 2025
87ad3e2
Merge pull request #37 from Code-4-Community/add_labels
maxn990 Aug 22, 2025
f6d4058
Created Label component
aaronashby Aug 22, 2025
b244352
Created LabelsView component
aaronashby Aug 24, 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
f14408e
added get task by id route
maxn990 Aug 24, 2025
9f6b559
added route to get all labels
maxn990 Aug 24, 2025
821adef
Merge pull request #43 from Code-4-Community/mn-get-task-by-id
maxn990 Aug 24, 2025
8a1b263
Made requested changes
aaronashby Aug 25, 2025
c814071
Included TaskCard in component rendering
dburkhart07 Aug 25, 2025
1534f9d
added test
maxn990 Aug 25, 2025
a902f1c
Merge branch 'main' into aa-35-create-labels-viewer
aaronashby Aug 25, 2025
fea4e2d
Changed state-updating logic
aaronashby Aug 25, 2025
c122e3a
Merge pull request #44 from Code-4-Community/mn-get-all-labels
amywng Aug 26, 2025
7f319d0
Merge pull request #42 from Code-4-Community/33-fetch-and-move-tasks
amywng Aug 26, 2025
5f22a40
create component for create/edit tasks
amywng Aug 26, 2025
f012dd1
change root and task card styling fixes
amywng Aug 26, 2025
38af65e
Update task.controller.ts
maxn990 Aug 26, 2025
100fb02
Merge pull request #46 from Code-4-Community/amy/style-fixes
maxn990 Aug 26, 2025
4d99db0
requested changes
amywng Aug 26, 2025
3a5b047
got rid of swagger documentation and duplicate error message in contr…
chnnick Aug 26, 2025
9da7689
deleted duplicate docs comment
chnnick Aug 26, 2025
5fa0775
Merge branch 'main' into aa-35-create-labels-viewer
aaronashby Aug 26, 2025
8a2439d
fixed describe in controller spec
maxn990 Aug 26, 2025
b8a27d9
Integrated with backend
aaronashby Aug 26, 2025
1cb0afa
Merge pull request #47 from Code-4-Community/mn-fix-task-route
amywng Aug 26, 2025
d8b1f4d
Merge pull request #45 from Code-4-Community/amy/create-edit-task
amywng Aug 26, 2025
a6ff7d8
Merge branch 'main' into 5-delete-tasks-route
maxn990 Aug 26, 2025
3f1d530
Merge pull request #22 from Code-4-Community/5-delete-tasks-route
maxn990 Aug 26, 2025
6e23842
Merge branch 'main' into aa-35-create-labels-viewer
aaronashby Aug 26, 2025
c763687
test
maxn990 Aug 26, 2025
ac36e10
added title field to header props
Ryaken-Nakamoto Aug 27, 2025
466b43a
removed undefined type from title attribute
Ryaken-Nakamoto Aug 27, 2025
e14f77d
changed comment
Ryaken-Nakamoto Aug 27, 2025
5c4bcf0
Re-added "Add Label" button
aaronashby Aug 27, 2025
aedf74e
Moved button outside container
aaronashby Aug 27, 2025
1fc2f40
Merge pull request #41 from Code-4-Community/aa-35-create-labels-viewer
aaronashby Aug 27, 2025
787fd1f
implemented DueDate component
Ryaken-Nakamoto Aug 27, 2025
1667cf4
removed excess due date label
Ryaken-Nakamoto Aug 27, 2025
4c6ab37
update design to match figma
amywng Aug 27, 2025
90747ca
changed to displayTitle
Ryaken-Nakamoto Aug 28, 2025
248884f
Implemented opening and closing CreateEditTask
aaronashby Aug 28, 2025
4104d87
category buttons
chnnick Aug 29, 2025
ba4069c
Merge pull request #40 from Code-4-Community/23-header
maxn990 Aug 29, 2025
bf88fac
Merge pull request #50 from Code-4-Community/36-due-date
maxn990 Aug 29, 2025
482b4ee
header style fix and make title not required, update root to include …
amywng Aug 29, 2025
cb35cfc
Merge pull request #52 from Code-4-Community/amy/style-fixes
maxn990 Aug 29, 2025
79ebcc7
takes in an optional category that will preset a choice on the catego…
chnnick Aug 29, 2025
3cbf545
updated text size of labels, added margin to left that matches the bu…
chnnick Aug 29, 2025
ce83b61
defaults to draft, got rid of unused imports
chnnick Aug 30, 2025
4567af8
Merge pull request #53 from Code-4-Community/34-category-buttons
amywng Aug 30, 2025
09b30f2
Merge branch 'main' into aa-49-open-edit-task
aaronashby Aug 30, 2025
ad4437b
Fixed positioning
aaronashby Aug 30, 2025
45a56ca
Initial layout. Just needs a few small edits
dburkhart07 Aug 30, 2025
df41cff
Final commit
dburkhart07 Aug 30, 2025
f892a3e
Final commit
dburkhart07 Aug 30, 2025
8b416aa
Final commit
dburkhart07 Aug 30, 2025
5209116
Merge pull request #51 from Code-4-Community/aa-49-open-edit-task
amywng Aug 31, 2025
a578c98
Made updates based on Figma
dburkhart07 Aug 31, 2025
7bb2b57
Implemented final changes
dburkhart07 Aug 31, 2025
7d69925
Implemented final changes
dburkhart07 Aug 31, 2025
54e011a
Merge pull request #54 from Code-4-Community/38-create-label-popup
maxn990 Sep 1, 2025
25d3c2f
Made initial changes. Now have label addition occuring in the fronten…
dburkhart07 Sep 4, 2025
3f3363f
Made a ton of changes
dburkhart07 Sep 5, 2025
185f9f1
Final commit
dburkhart07 Sep 6, 2025
69f749e
Final commit
dburkhart07 Sep 6, 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
9 changes: 9 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,9 @@
import { IsString, IsHexColor } from 'class-validator';

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

@IsHexColor()
color: string;
}
90 changes: 90 additions & 0 deletions apps/backend/src/label/label.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
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),
),
getAllLabels: jest.fn(() => Promise.resolve([mockLabel])),
};

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

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

export const mockLabel2: Label = {
id: 2,
name: 'Test Label 2',
color: '#802b2bff',
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);
});
});

/* Test for retrieve all labels */
describe('GET /labels', () => {
it('should return an array of labels', async () => {
jest
.spyOn(mockLabelService, 'getAllLabels')
.mockResolvedValue([mockLabel]);

const res = await controller.getAllLabels();

expect(res).toEqual([mockLabel]);
expect(mockLabelService.getAllLabels).toHaveBeenCalled();
});
it('should return an array of labels with 2 labels', async () => {
jest
.spyOn(mockLabelService, 'getAllLabels')
.mockResolvedValue([mockLabel, mockLabel2]);

const res = await controller.getAllLabels();

expect(res).toEqual([mockLabel, mockLabel2]);
expect(mockLabelService.getAllLabels).toHaveBeenCalled();
});
});
});
40 changes: 40 additions & 0 deletions apps/backend/src/label/label.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
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);
}

/** Gets all labels.
* @returns An array of all labels.
*/
@Get()
async getAllLabels(): Promise<Label[]> {
return this.labelsService.getAllLabels();
}
}
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 {}
104 changes: 104 additions & 0 deletions apps/backend/src/label/label.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
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',
color: '#000000',
};

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

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

const mockInvalidCreateLabelDTO3 = {
name: 'Label 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"),
);
});
});

describe('getAllLabels', () => {
it('should return an array of labels', async () => {
mockLabelsRepository.find.mockResolvedValue([mockLabel]);

const result = await service.getAllLabels();

expect(result).toEqual([mockLabel]);
expect(mockLabelsRepository.find).toHaveBeenCalled();
});
});
});
39 changes: 39 additions & 0 deletions apps/backend/src/label/label.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
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);
}

// Retrieves all labels
async getAllLabels(): Promise<Label[]> {
return this.labelRepository.find({ relations: ['tasks'] });
}
}
Loading
Loading