Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 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
9f3294a
controller and dto
IsabellaB876 Nov 2, 2025
9f9eaaf
dto file
IsabellaB876 Nov 2, 2025
27967b7
add optional publishing_name field on User
builderpepc Nov 9, 2025
f2c91d7
Merge pull request #30 from Code-4-Community/bz-update-anthology
SlothfulDreams Nov 12, 2025
2a52b52
Add DELETE /anthology/:id endpoint with 200 response and 404 handling
Nov 22, 2025
dc5d1ca
Merge pull request #47 from alaatamam/feature/delete-endpoint-antho
alaatamam Nov 22, 2025
6d04c75
feat: implement Archived Publications page with modal interaction
Nov 22, 2025
7096b6e
feat: add dynamic search filtering for archived publications (title +…
Nov 22, 2025
4e837fb
feat: add dynamic search filtering + author byline to archived public…
Nov 22, 2025
a8b5fbc
Merge pull request #32 from Code-4-Community/troy-user-changes
builderpepc Nov 22, 2025
2cc7c00
implement individual publication UI
builderpepc Nov 23, 2025
10174f5
UI updates
builderpepc Nov 23, 2025
789134a
add unimplemented fields to frontend model
builderpepc Nov 23, 2025
74a93f1
format
builderpepc Nov 23, 2025
fd3f3f6
updated typescript + eslint versions (linter issue)
rjuvekar137 Nov 23, 2025
db10382
Merge pull request #50 from Code-4-Community/troy-publication-view
builderpepc Dec 1, 2025
72a3786
Merge branch 'main' into feature/archived-publications
rjuvekar137 Dec 2, 2025
df8c2e5
Merge pull request #48 from alaatamam/feature/archived-publications
IsabellaB876 Dec 3, 2025
3af472f
ui
SlothfulDreams Dec 3, 2025
aed4954
Merge pull request #49 from alaatamam/feature/archived-publications-s…
rjuvekar137 Dec 4, 2025
436991d
navigation between archive + publication view
rjuvekar137 Dec 4, 2025
0046fa5
merge conflict fix
SlothfulDreams Dec 4, 2025
0045cd5
Merge pull request #55 from Code-4-Community/ui/bz-archive-pub-page
SlothfulDreams Dec 4, 2025
1ddd089
Merge branch 'main' into rj-navigation-styling
rjuvekar137 Dec 4, 2025
0eb0f12
merge conflict fix
rjuvekar137 Dec 4, 2025
325d0b9
added side bar to the individual publication view
rjuvekar137 Dec 4, 2025
0e025ed
same mock data for publications + archive
rjuvekar137 Dec 4, 2025
3a395f6
added sample data provided
rjuvekar137 Dec 4, 2025
27f9c6e
minor navigation mismatch
rjuvekar137 Dec 4, 2025
c30ac20
edits to tag styling
rjuvekar137 Dec 4, 2025
8226222
changed image styling for individiual pub view
rjuvekar137 Dec 4, 2025
7784f9c
Merge pull request #54 from Code-4-Community/rj-navigation-styling
rjuvekar137 Dec 5, 2025
ae10dee
Merge branch 'main' of https://github.com/Code-4-Community/826-boston…
rjuvekar137 Dec 5, 2025
c765015
Merge pull request #31 from Code-4-Community/get-post-story-endpoints
rjuvekar137 Dec 5, 2025
6617240
changed placeholder image
rjuvekar137 Dec 5, 2025
69e15f4
Merge pull request #56 from Code-4-Community/rj-individual-pub-styling
rjuvekar137 Dec 5, 2025
02fc2ee
BOS-61: refactored backend entities
Ryaken-Nakamoto Jan 24, 2026
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
43 changes: 43 additions & 0 deletions apps/backend/src/anthology/anthology.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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('/:anthologyId')
async removeAnthology(
@Param('anthologyId', ParseIntPipe) anthologyId: number,
): Promise<{ message: string }> {
await this.anthologyService.remove(anthologyId);
return { message: 'Anthology deleted successfully' };
}
}
52 changes: 52 additions & 0 deletions apps/backend/src/anthology/anthology.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
Entity,
Column,
IntegerType,

Check warning on line 4 in apps/backend/src/anthology/anthology.entity.ts

View workflow job for this annotation

GitHub Actions / pre-deploy

'IntegerType' is defined but never used
PrimaryGeneratedColumn,
OneToMany,
ManyToOne,

Check warning on line 7 in apps/backend/src/anthology/anthology.entity.ts

View workflow job for this annotation

GitHub Actions / pre-deploy

'ManyToOne' is defined but never used
} from 'typeorm';

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

import { Story } from '../story/story.entity';
import { InventoryHolding } from '../inventory-holding/inventory-holding.entity';

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

@Column()
title: string;

@Column()
description: string;

@Column({ type: 'int' })
published_year: number;

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

@Column()
status: AnthologyStatus;

@Column()
pub_level: AnthologyPubLevel;

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

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

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

@OneToMany(() => Story, (story) => story.anthology)
stories: Story[];

@OneToMany(() => InventoryHolding, (ih) => ih.anthology)
holdings: InventoryHolding[];
}
18 changes: 18 additions & 0 deletions apps/backend/src/anthology/anthology.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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';

Check warning on line 6 in apps/backend/src/anthology/anthology.module.ts

View workflow job for this annotation

GitHub Actions / pre-deploy

'AuthService' is defined but never used
import { JwtStrategy } from '../auth/jwt.strategy';

Check warning on line 7 in apps/backend/src/anthology/anthology.module.ts

View workflow job for this annotation

GitHub Actions / pre-deploy

'JwtStrategy' is defined but never used
import { CurrentUserInterceptor } from '../interceptors/current-user.interceptor';
import { AuthModule } from '../auth/auth.module';
import { UsersModule } from '../users/users.module';

@Module({
imports: [TypeOrmModule.forFeature([Anthology]), AuthModule, UsersModule],
controllers: [AnthologyController],
providers: [AnthologyService, CurrentUserInterceptor],
exports: [AnthologyService],
})
export class AnthologyModule {}
98 changes: 98 additions & 0 deletions apps/backend/src/anthology/anthology.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
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[],
photo_url?: 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,
photo_url,
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 } });
}

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 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);
}
}
79 changes: 79 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,79 @@
import {
IsString,
IsNumber,
IsOptional,
IsEnum,
IsArray,
} from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { AnthologyStatus, AnthologyPubLevel } from '../types';

//TODO: outdated DTO needs to match the schema
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',
}
13 changes: 11 additions & 2 deletions apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,20 @@ import { TypeOrmModule } from '@nestjs/typeorm';

import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TaskModule } from './task/task.module';
import { AuthorModule } from './author/author.module';
import { InventoryModule } from './inventory/inventory.module';
import { InventoryHoldingModule } from './inventory-holding/inventory-holding.module';
import AppDataSource from './data-source';
import { StoryModule } from './story/story.module';

@Module({
imports: [TypeOrmModule.forRoot(AppDataSource.options), TaskModule],
imports: [
TypeOrmModule.forRoot(AppDataSource.options),
AuthorModule,
InventoryModule,
InventoryHoldingModule,
StoryModule,
],
controllers: [AppController],
providers: [AppService],
})
Expand Down
Loading