Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4b7a22b
initial backend setup + error cleanup
rjuvekar137 Sep 17, 2025
3323502
create anthology entity
builderpepc Oct 4, 2025
718d69e
add anthology service
builderpepc Oct 4, 2025
f5d38bf
feature: added anthology controller
Oct 5, 2025
234c738
restore the example.env to the default template
Oct 5, 2025
1792de1
added library controller, entity, module, service
robpatterson13 Oct 5, 2025
deb0728
actually saved library files this time
robpatterson13 Oct 5, 2025
784f17d
story service file
IsabellaB876 Oct 5, 2025
2c22884
Merge pull request #17 from alaatamam/feature/anthology-controller
alaatamam Oct 12, 2025
c2c73ec
Implemented Anthology Module and small update to Anthology Controller
Oct 12, 2025
95b96a0
Merge branch 'main' into feature/anthology-module
alaatamam Oct 12, 2025
76a306d
Merge pull request #22 from alaatamam/feature/anthology-module
alaatamam Oct 12, 2025
c29f586
Merge pull request #19 from Code-4-Community/create-story-entity
alaatamam Oct 12, 2025
eed27a1
removed unnecessary imports from library controller
robpatterson13 Oct 13, 2025
018489f
Merge pull request #23 from Code-4-Community/rob-library
robpatterson13 Oct 13, 2025
305e3ef
adding to story controller + module
IsabellaB876 Oct 18, 2025
0a6d987
add API route to get anthologies from library instances
builderpepc Oct 19, 2025
6beaf82
add tests for Library
builderpepc Oct 19, 2025
232a32c
add endpoint to create anthologies, and tests
builderpepc Oct 19, 2025
eeef949
Merge pull request #24 from Code-4-Community/troy/new-library-endpoints
alaatamam Oct 19, 2025
4a58890
done
SlothfulDreams Oct 26, 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
42 changes: 42 additions & 0 deletions apps/backend/src/anthology/anthology.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {
Controller,
Get,
Delete,
Param,
ParseIntPipe,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import { AnthologyService } from './anthology.service';
import { Anthology } from './anthology.entity';
import { AuthGuard } from '@nestjs/passport';
import { CurrentUserInterceptor } from '../interceptors/current-user.interceptor';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';

@ApiTags('Anthologies')
@ApiBearerAuth()
@Controller('anthologies')
@UseGuards(AuthGuard('jwt'))
@UseInterceptors(CurrentUserInterceptor)
export class AnthologyController {
constructor(private readonly anthologyService: AnthologyService) {}

@Get('/:id')
async getAnthology(
@Param('id', ParseIntPipe) id: number,
): Promise<Anthology> {
return this.anthologyService.findOne(id);
}

@Get()
async getAllAnthologies(): Promise<Anthology[]> {
return this.anthologyService.findAll();
}

@Delete('/:id')
async removeAnthology(
@Param('id', ParseIntPipe) id: number,
): Promise<Anthology> {
return this.anthologyService.remove(id);
}
}
49 changes: 49 additions & 0 deletions apps/backend/src/anthology/anthology.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Entity, Column, IntegerType } from 'typeorm';

import { AnthologyStatus, AnthologyPubLevel } from './types';

@Entity()
export class Anthology {
@Column({ primary: true })
id: number;

@Column()
title: string;

@Column()
description: string;

@Column()
published_year: IntegerType;

@Column({ nullable: true })
programs?: string[] | string;

@Column({ nullable: true })
inventory?: IntegerType;

@Column()
status: AnthologyStatus;

@Column()
pub_level: AnthologyPubLevel;

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

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

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

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

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

// TODO once Library is implemented
// @Column()
// library_id:
}
20 changes: 20 additions & 0 deletions apps/backend/src/anthology/anthology.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AnthologyController } from './anthology.controller';
import { AnthologyService } from './anthology.service';
import { Anthology } from './anthology.entity';
import { AuthService } from '../auth/auth.service';
import { JwtStrategy } from '../auth/jwt.strategy';
import { CurrentUserInterceptor } from '../interceptors/current-user.interceptor';

@Module({
imports: [TypeOrmModule.forFeature([Anthology])],
controllers: [AnthologyController],
providers: [
AnthologyService,
AuthService,
JwtStrategy,
CurrentUserInterceptor,
],
})
export class AnthologyModule {}
123 changes: 123 additions & 0 deletions apps/backend/src/anthology/anthology.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';

import { Anthology } from './anthology.entity';
import { AnthologyStatus, AnthologyPubLevel } from './types';

@Injectable()
export class AnthologyService {
constructor(
@InjectRepository(Anthology) private repo: Repository<Anthology>,
) {}

async create(
title: string,
description: string,
published_year: number,
status: AnthologyStatus,
pub_level: AnthologyPubLevel,
programs?: string[] | string,
inventory?: number,
photo_url?: string,
genre?: string,
theme?: string,
isbn?: string,
shopify_url?: string,
) {
const anthologyId = (await this.repo.count()) + 1;
const anthology = this.repo.create({
id: anthologyId,
title,
description,
published_year,
status,
pub_level,
programs,
inventory,
photo_url,
genre,
theme,
isbn,
shopify_url,
});

return this.repo.save(anthology);
}

findOne(id: number) {
if (!id) {
return null;
}

return this.repo.findOneBy({ id });
}

findAll() {
return this.repo.find();
}

findByStatus(status: AnthologyStatus) {
return this.repo.find({ where: { status } });
}

findByPubLevel(pub_level: AnthologyPubLevel) {
return this.repo.find({ where: { pub_level } });
}

findByYear(published_year: number) {
return this.repo.find({ where: { published_year } });
}

findByGenre(genre: string) {
return this.repo.find({ where: { genre } });
}

findByTheme(theme: string) {
return this.repo.find({ where: { theme } });
}

async update(id: number, attrs: Partial<Anthology>) {
const anthology = await this.findOne(id);

if (!anthology) {
throw new NotFoundException('Anthology not found');
}

Object.assign(anthology, attrs);

return this.repo.save(anthology);
}

async remove(id: number) {
const anthology = await this.findOne(id);

if (!anthology) {
throw new NotFoundException('Anthology not found');
}

return this.repo.remove(anthology);
}

async updateInventory(id: number, inventory: number) {
const anthology = await this.findOne(id);

if (!anthology) {
throw new NotFoundException('Anthology not found');
}

anthology.inventory = inventory;
return this.repo.save(anthology);
}

async updateStatus(id: number, status: AnthologyStatus) {
const anthology = await this.findOne(id);

if (!anthology) {
throw new NotFoundException('Anthology not found');
}

anthology.status = status;
return this.repo.save(anthology);
}
}
78 changes: 78 additions & 0 deletions apps/backend/src/anthology/dtos/create-anthology.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {
IsString,
IsNumber,
IsOptional,
IsEnum,
IsArray,
} from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { AnthologyStatus, AnthologyPubLevel } from '../types';

export class CreateAnthologyDto {
@ApiProperty({ description: 'Title of the anthology' })
@IsString()
title: string;

@ApiProperty({ description: 'Description of the anthology' })
@IsString()
description: string;

@ApiProperty({ description: 'Year the anthology was published' })
@IsNumber()
published_year: number;

@ApiProperty({
description: 'Status of the anthology',
enum: AnthologyStatus,
example: AnthologyStatus.DRAFTING,
})
@IsEnum(AnthologyStatus)
status: AnthologyStatus;

@ApiProperty({
description: 'Publication level of the anthology',
enum: AnthologyPubLevel,
example: AnthologyPubLevel.ZINE,
})
@IsEnum(AnthologyPubLevel)
pub_level: AnthologyPubLevel;

@ApiPropertyOptional({
description: 'Programs associated with the anthology',
type: [String],
})
@IsOptional()
@IsArray()
@IsString({ each: true })
programs?: string[];

@ApiPropertyOptional({ description: 'Inventory count' })
@IsOptional()
@IsNumber()
inventory?: number;

@ApiPropertyOptional({ description: 'URL to anthology photo' })
@IsOptional()
@IsString()
photo_url?: string;

@ApiPropertyOptional({ description: 'Genre of the anthology' })
@IsOptional()
@IsString()
genre?: string;

@ApiPropertyOptional({ description: 'Theme of the anthology' })
@IsOptional()
@IsString()
theme?: string;

@ApiPropertyOptional({ description: 'ISBN of the anthology' })
@IsOptional()
@IsString()
isbn?: string;

@ApiPropertyOptional({ description: 'Shopify URL for purchasing' })
@IsOptional()
@IsString()
shopify_url?: string;
}
4 changes: 4 additions & 0 deletions apps/backend/src/anthology/dtos/update-anthology.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/mapped-types';
import { CreateAnthologyDto } from './create-anthology.dto';

export class UpdateAnthologyDto extends PartialType(CreateAnthologyDto) {}
13 changes: 13 additions & 0 deletions apps/backend/src/anthology/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export enum AnthologyStatus {
ARCHIVED = 'Archived',
NOT_STARTED = 'NotStarted',
DRAFTING = 'Drafting',
CAN_BE_SHARED = 'CanBeShared',
}

export enum AnthologyPubLevel {
ZINE = 'Zine',
CHAPBOOK = 'Chapbook',
PERFECT_BOUND = 'PerfectBound',
SIGNATURE = 'Signature',
}
3 changes: 1 addition & 2 deletions apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ 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';

@Module({
imports: [TypeOrmModule.forRoot(AppDataSource.options), TaskModule],
imports: [TypeOrmModule.forRoot(AppDataSource.options)],
controllers: [AppController],
providers: [AppService],
})
Expand Down
3 changes: 1 addition & 2 deletions apps/backend/src/data-source.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { DataSource } from 'typeorm';
import { PluralNamingStrategy } from './strategies/plural-naming.strategy';
import { Task } from './task/types/task.entity';
import * as dotenv from 'dotenv';

dotenv.config();
Expand All @@ -12,7 +11,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: [],
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
Loading
Loading