Skip to content

Commit df89552

Browse files
authored
Merge pull request #379 from mezonai/dev
Release Jan26
2 parents dcab302 + 50e2630 commit df89552

File tree

133 files changed

+3485
-2611
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

133 files changed

+3485
-2611
lines changed

backend/src/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { LoggerModule } from "@libs/logger";
2828
import { MezonModule } from "@features/mezon-noti-bot/mezon.module";
2929
import { TempStorageModule } from "@features/temp-storage/temp-storage.module";
3030
import { BotGeneratorModule } from "@features/bot-generator/bot-generator.module";
31+
import { FavoriteAppModule } from "@features/favorite-app/favorite-app.module";
3132
import { CacheModule } from "@libs/cache";
3233

3334
@Module({
@@ -81,6 +82,7 @@ import { CacheModule } from "@libs/cache";
8182
AppVersionModule,
8283
TempStorageModule,
8384
BotGeneratorModule,
85+
FavoriteAppModule
8486
],
8587
controllers: [],
8688
providers: [],

backend/src/domain/entities/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ export * from "./schema/tag.entity"
1010
export * from "./schema/user.entity"
1111
export * from "./schema/appVersion.entity"
1212
export * from "./schema/tempFile.entity"
13+
export * from "./schema/favorite-app.entity"
1314

backend/src/domain/entities/schema/app.entity.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Column, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, PrimaryColumn, Unique } from "typeorm";
22

33
import { AppStatus } from "@domain/common/enum/appStatus";
4-
import { Link, AppReviewHistory, Rating, Tag, User, AppVersion } from "@domain/entities";
4+
import { Link, AppReviewHistory, Rating, Tag, User, AppVersion, FavoriteApp } from "@domain/entities";
55

66
import { BaseSoftDelete } from "../base";
77
import { MezonAppType } from "@domain/common/enum/mezonAppType";
@@ -49,4 +49,9 @@ export class App extends BaseApp {
4949

5050
@OneToMany(() => AppVersion, (version) => version.app)
5151
public versions: AppVersion[];
52+
53+
@OneToMany(() => FavoriteApp, (favoriteApp) => favoriteApp.app)
54+
public favorites: FavoriteApp[];
55+
56+
public isFavorited?: boolean;
5257
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Column, Entity, JoinColumn, ManyToOne, Unique } from "typeorm";
2+
import { App, BaseSoftDelete, User } from "@domain/entities";
3+
4+
@Entity("favorite_app")
5+
@Unique(["userId", "appId"])
6+
export class FavoriteApp extends BaseSoftDelete {
7+
@Column()
8+
userId: string;
9+
10+
@Column()
11+
appId: string;
12+
13+
@ManyToOne(() => User)
14+
@JoinColumn({ name: "userId" })
15+
user: User;
16+
17+
@ManyToOne(() => App)
18+
@JoinColumn({ name: "appId" })
19+
app: App;
20+
}

backend/src/domain/entities/schema/mailTemplate.entity.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,7 @@ export class MailTemplate extends BaseSoftDelete {
2525
default: RepeatInterval.DAILY,
2626
})
2727
public repeatInterval: RepeatInterval
28+
29+
@Column({ type: 'timestamptz', nullable: true })
30+
public lastSentAt?: Date;
2831
}

backend/src/domain/entities/schema/tag.entity.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ export class Tag extends BaseSoftDelete {
1212
@Column()
1313
public slug: string;
1414

15+
@Column({ default: 'magenta' })
16+
public color: string;
17+
1518
@ManyToMany(() => App, (app) => app.tags)
1619
public apps: App[];
1720
}

backend/src/domain/entities/schema/user.entity.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from "typeorm";
88

99
import { Role } from "@domain/common/enum/role";
10-
import { App, Link, Media, Rating, TempFile } from "@domain/entities";
10+
import { App, Link, Media, Rating, TempFile, FavoriteApp } from "@domain/entities";
1111

1212
import { BaseSoftDelete } from "../base";
1313
import { BotWizard } from "@domain/entities/schema/botWizard.entity";
@@ -42,6 +42,9 @@ export class User extends BaseSoftDelete {
4242
@Column({ nullable: false, default: false })
4343
public isFirstLogin: boolean;
4444

45+
@OneToMany(() => FavoriteApp, (favoriteApp) => favoriteApp.user)
46+
public favoriteApps: FavoriteApp[];
47+
4548
@OneToMany(() => Rating, (rating) => rating.user)
4649
public ratings: Rating[];
4750

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ApiProperty } from "@nestjs/swagger";
2+
import { IsUUID } from "class-validator";
3+
import { PaginationQuery } from "@domain/common/dtos/request.dto";
4+
5+
export class AddFavoriteAppRequest {
6+
@ApiProperty()
7+
@IsUUID()
8+
id: string;
9+
}
10+
11+
export class GetFavoritesAppRequest extends PaginationQuery {
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { ApiProperty } from "@nestjs/swagger";
2+
import { Expose, Type } from "class-transformer";
3+
import { GetMezonAppDetailsResponse } from "@features/mezon-app/dtos/response";
4+
import { TagInMezonAppDetailResponse } from "@features/tag/dtos/response";
5+
6+
export class FavoriteAppResponseDto extends GetMezonAppDetailsResponse {
7+
@Expose()
8+
@ApiProperty({ type: () => [TagInMezonAppDetailResponse] })
9+
@Type(() => TagInMezonAppDetailResponse)
10+
public tags: TagInMezonAppDetailResponse[];
11+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { Body, Controller, Delete, Get, Param, Post, Query } from "@nestjs/common";
2+
import { ApiBearerAuth, ApiTags, ApiResponse } from "@nestjs/swagger";
3+
4+
import { User } from "@domain/entities";
5+
import { GetUserFromHeader } from "@libs/decorator/getUserFromHeader.decorator";
6+
import { FavoriteAppService } from "./favorite-app.service";
7+
import { AddFavoriteAppRequest, GetFavoritesAppRequest } from "./dtos/request";
8+
9+
@ApiTags("FavoriteApps")
10+
@Controller("favorite-app")
11+
@ApiBearerAuth()
12+
export class FavoriteAppController {
13+
constructor(private readonly favoriteAppService: FavoriteAppService) {}
14+
15+
@Get()
16+
@ApiResponse({ status: 200, description: "Get list of favorite bots" })
17+
async getFavoriteApps(
18+
@GetUserFromHeader() user: User,
19+
@Query() query: GetFavoritesAppRequest
20+
) {
21+
return this.favoriteAppService.getMyFavoriteApps(user.id, query);
22+
}
23+
24+
@Get(":id")
25+
@ApiResponse({ status: 200, description: "Get favorite bot detail" })
26+
async getFavoriteAppDetail(
27+
@GetUserFromHeader() user: User,
28+
@Param("id") id: string
29+
) {
30+
return this.favoriteAppService.getFavoriteAppDetail(user.id, id);
31+
}
32+
33+
@Post()
34+
@ApiResponse({ status: 201, description: "Bot added to favorites successfully" })
35+
async addFavoriteApp(
36+
@GetUserFromHeader() user: User,
37+
@Body() body: AddFavoriteAppRequest
38+
) {
39+
return this.favoriteAppService.addFavoriteApp(user.id, body.id);
40+
}
41+
42+
@Delete(":id")
43+
@ApiResponse({ status: 200, description: "Bot removed from favorites successfully" })
44+
async removeFavoriteApp(
45+
@GetUserFromHeader() user: User,
46+
@Param("id") id: string
47+
) {
48+
return this.favoriteAppService.removeFavoriteApp(user.id, id);
49+
}
50+
}

0 commit comments

Comments
 (0)