From cbb8e637b99bb82b321f4815ede576f6ece07004 Mon Sep 17 00:00:00 2001 From: dbaric99 Date: Wed, 4 Dec 2024 01:08:56 +0100 Subject: [PATCH 01/10] update schema --- apps/api/db/schema.ts | 401 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 370 insertions(+), 31 deletions(-) diff --git a/apps/api/db/schema.ts b/apps/api/db/schema.ts index 0a060a70..5a44d263 100644 --- a/apps/api/db/schema.ts +++ b/apps/api/db/schema.ts @@ -2,6 +2,7 @@ import { relations } from 'drizzle-orm'; import { boolean, integer, + json, pgEnum, pgTable, primaryKey, @@ -10,6 +11,108 @@ import { timestamp, } from 'drizzle-orm/pg-core'; +export const companyCategory = pgEnum('company_category', [ + 'gold', + 'silver', + 'bronze', + 'media', + 'friend', +]); + +export const theme = pgEnum('theme', ['dev', 'design', 'marketing', 'tech']); + +export const eventType = pgEnum('event_type', [ + 'lecture', + 'workshop', + 'flyTalk', + 'campfireTalk', + 'panel', + 'other', +]); + +export const surveyQuestionInputType = pgEnum('survey_question_input_type', [ + 'input', + 'textarea', + 'rating', +]); + +export const surveyQuestionType = pgEnum('survey_question_type', [ + 'workshop', + 'lecture', + 'company', +]); + +// new enums +export const shopItemType = pgEnum('shop_item_type', [ + 'mug', + 'shirt', + 'hoodie', + 'sticker', +]); + +export const shoppingCartItemStage = pgEnum('shopping_cart_item_stage', [ + 'collected', + 'uncollected', +]); + +export const colors = pgEnum('colors', [ + 'yellow', + 'orange', + 'brown', + 'purple', + 'green', + 'white', + 'red', + 'gray', +]); + +export const face = pgEnum('face', [ + 'default', + 'eyelashes', + 'angry', + 'crying', + 'mustache', + 'nose_ring', + 'tattoo', + 'mole', +]); + +export const accessory = pgEnum('accessory', [ + 'default', + 'sunglasses', + 'crown', + 'angel', + 'beret', + 'ninja', + 'headphones', + 'flower', +]); + +export const body = pgEnum('body', [ + 'default', + 'scarf', + 'chain', + 'basketball', + 'macbook', + 'sunflower', + 'cats', + 'dumbell', +]); + +export const notificationType = pgEnum('notification_type', [ + 'announcment', + 'event_reminder', + 'achievement', + 'emergency', + 'survey', +]); + +export const notificationStatus = pgEnum('notification_status', [ + 'pending', + 'delivered', + 'read', +]); + export const achievement = pgTable('achievement', { id: serial('id').primaryKey(), name: text('name').notNull(), @@ -69,14 +172,6 @@ export const achievementToCodeRelations = relations( }), ); -export const companyCategory = pgEnum('company_category', [ - 'gold', - 'silver', - 'bronze', - 'media', - 'friend', -]); - export const company = pgTable('company', { id: serial('id').primaryKey(), password: text('password'), @@ -105,6 +200,31 @@ export const companyRelations = relations(company, ({ one, many }) => ({ booth: one(booth), })); +export const companyToFlyTalk = pgTable( + 'company_to_fly_talk', + { + companyId: integer('company_id').references(() => company.id), + eventId: integer('event_id').references(() => event.id), + }, + (t) => ({ + pk: primaryKey({ columns: [t.companyId, t.eventId] }), + }), +); + +export const companyToFlyTalkRelations = relations( + companyToFlyTalk, + ({ one }) => ({ + company: one(company, { + fields: [companyToFlyTalk.companyId], + references: [company.id], + }), + event: one(event, { + fields: [companyToFlyTalk.eventId], + references: [event.id], + }), + }), +); + export const job = pgTable('job', { id: serial('id').primaryKey(), position: text('position').notNull(), @@ -124,17 +244,6 @@ export const jobRelations = relations(job, ({ one }) => ({ }), })); -export const theme = pgEnum('theme', ['dev', 'design', 'marketing', 'tech']); - -export const eventType = pgEnum('event_type', [ - 'lecture', - 'workshop', - 'flyTalk', - 'campfireTalk', - 'panel', - 'other', -]); - export const event = pgTable('event', { id: serial('id').primaryKey(), name: text('name').notNull(), @@ -233,18 +342,6 @@ export const frequentlyAskedQuestion = pgTable('frequently_asked_question', { answer: text('answer').notNull(), }); -export const surveyQuestionInputType = pgEnum('survey_question_input_type', [ - 'input', - 'textarea', - 'rating', -]); - -export const surveyQuestionType = pgEnum('survey_question_type', [ - 'workshop', - 'lecture', - 'company', -]); - export const surveyQuestion = pgTable('survey_question', { id: serial('id').primaryKey(), question: text('question').notNull(), @@ -258,9 +355,63 @@ export const notification = pgTable('notification', { id: serial('id').primaryKey(), title: text('title').notNull(), content: text('description'), + type: notificationType('type').notNull(), activatedAt: timestamp('activated_at'), + expiresAt: timestamp('expires_at'), + createdAt: timestamp('created_at').defaultNow(), + createdByUserId: integer('created_by_user_id').references(() => user.id), + eventId: integer('event_id').references(() => event.id), + isActive: boolean('is_active').default(true), }); +export const userNotification = pgTable( + 'user_notification', + { + id: serial('id').primaryKey(), + userId: integer('user_id') + .notNull() + .references(() => user.id), + notificationId: integer('notification_id') + .notNull() + .references(() => notification.id), + status: notificationStatus('status').notNull().default('pending'), + deliveredAt: timestamp('delivered_at'), + readAt: timestamp('read_at'), + }, + (t) => ({ + pk: primaryKey({ columns: [t.userId, t.notificationId] }), + }), +); + +export const userNotificationRelations = relations( + userNotification, + ({ one }) => ({ + user: one(user, { + fields: [userNotification.userId], + references: [user.id], + }), + notification: one(notification, { + fields: [userNotification.notificationId], + references: [notification.id], + }), + }), +); + +export const notificationRelations = relations( + notification, + ({ one, many }) => ({ + createdByUser: one(user, { + fields: [notification.createdByUserId], + references: [user.id], + }), + event: one(event, { + fields: [notification.eventId], + references: [event.id], + }), + userNotifications: many(userNotification), + }), +); + export const speaker = pgTable('speaker', { id: serial('id').primaryKey(), firstName: text('firstName').notNull(), @@ -322,3 +473,191 @@ export const boothRelations = relations(booth, ({ one }) => ({ references: [company.id], }), })); + +export const user = pgTable('user', { + id: serial('id').primaryKey(), + firstName: text('first_name').notNull(), + lastName: text('last_name').notNull(), + email: text('email').notNull().unique(), + phoneNumber: text('phone_number').notNull().unique(), + yearOfBirth: integer('year_of_birth').notNull(), + occupation: text('occupation'), + password: text('password'), + points: integer('points'), + newsletterConsent: boolean('newsletter_consent'), + companiesNewsletterConsent: boolean('companies_newsletter_consent'), + isDeleted: boolean('is_deleted'), + profilePhotoUrl: text('profile_photo_url'), +}); + +export const avatar = pgTable('avatar', { + id: serial('id').primaryKey(), + userId: integer('user_id').references(() => user.id), + color: colors('color'), + face: face('face'), + accessory: accessory('accessory'), + body: body('body'), +}); + +export const avatarRelations = relations(avatar, ({ one }) => ({ + user: one(user, { + fields: [avatar.userId], + references: [user.id], + }), +})); + +export const userToEvent = pgTable( + 'user_to_event', + { + userId: integer('user_id').references(() => user.id), + eventId: integer('event_id').references(() => event.id), + linkedinProfile: text('linkedin_profile'), + githubProfile: text('github_profile'), + portfolioProfile: text('portfolio_profile'), + cv: text('cv'), + description: text('description'), + }, + (t) => ({ + pk: primaryKey({ columns: [t.userId, t.eventId] }), + }), +); + +export const userToEventRelations = relations(userToEvent, ({ one }) => ({ + user: one(user, { + fields: [userToEvent.userId], + references: [user.id], + }), + event: one(event, { + fields: [userToEvent.eventId], + references: [event.id], + }), +})); + +export const userToInterest = pgTable( + 'user_to_interest', + { + userId: integer('user_id') + .notNull() + .references(() => user.id), + interestId: integer('interest_id') + .notNull() + .references(() => interest.id), + }, + (t) => ({ + pk: primaryKey({ columns: [t.userId, t.interestId] }), + }), +); + +export const userToInterestRelations = relations(userToInterest, ({ one }) => ({ + user: one(user, { + fields: [userToInterest.userId], + references: [user.id], + }), + interest: one(interest, { + fields: [userToInterest.interestId], + references: [interest.id], + }), +})); + +export const userToAchievement = pgTable( + 'user_to_achievement', + { + userId: integer('user_id') + .notNull() + .references(() => user.id), + achievementId: integer('achievement_id') + .notNull() + .references(() => achievement.id), + timeOfAchievement: timestamp('time_of_achievement'), + }, + (t) => ({ + pk: primaryKey({ columns: [t.userId, t.achievementId] }), + }), +); + +export const userToAchievementRelations = relations( + userToAchievement, + ({ one }) => ({ + user: one(user, { + fields: [userToAchievement.userId], + references: [user.id], + }), + achievement: one(achievement, { + fields: [userToAchievement.achievementId], + references: [achievement.id], + }), + }), +); + +export const shopItem = pgTable('shop_item', { + id: serial('id').primaryKey(), + type: shopItemType('type'), + itemName: text('item_name'), + quantity: integer('quantity'), + price: integer('price'), +}); + +export const shoppingCart = pgTable( + 'shopping_cart', + { + shopItemId: integer('shop_item_id').references(() => shopItem.id), + userId: integer('user_id').references(() => user.id), + quantity: integer('quantity'), + stage: shoppingCartItemStage('stage'), + orderedAt: timestamp('ordered_at'), + takeByTime: timestamp('take_by_time'), + }, + (t) => ({ + pk: primaryKey({ columns: [t.userId, t.shopItemId] }), + }), +); + +export const shoppingCartRelations = relations(shoppingCart, ({ one }) => ({ + shopItem: one(shopItem, { + fields: [shoppingCart.shopItemId], + references: [shopItem.id], + }), + user: one(user, { + fields: [shoppingCart.userId], + references: [user.id], + }), +})); + +export const userRelations = relations(user, ({ many }) => ({ + userToEvent: many(userToEvent), + userToInterest: many(userToInterest), + userToAchievement: many(userToAchievement), + avatar: many(avatar), + userNotifications: many(userNotification), + notifications: many(notification), + shoppingCart: many(shoppingCart), +})); + +export const notificationTemplate = pgTable('notification_template', { + id: serial('id').primaryKey(), + name: text('name').notNull(), + titleTemplate: text('title_template').notNull(), + contentTemplate: text('content_template').notNull(), + type: notificationType('type').notNull(), + createdAt: timestamp('created_at').defaultNow(), +}); + +export const rating = pgTable('rating', { + id: serial('id').primaryKey(), + userId: integer('user_id'), + boothId: integer('booth_id').references(() => booth.id), + eventId: integer('event_id').references(() => event.id), + grades: json('grades'), + comment: text('comment'), +}); + +export const ratingRelations = relations(rating, ({ one }) => ({ + booth: one(booth, { + fields: [rating.boothId], + references: [booth.id], + }), + event: one(event, { + fields: [rating.eventId], + references: [event.id], + }), +})); From e5b01e1e80e4a4d3ed17d42f2b6daf724c35bf06 Mon Sep 17 00:00:00 2001 From: dbaric99 Date: Sun, 8 Dec 2024 10:47:54 +0100 Subject: [PATCH 02/10] Fix migration error --- apps/api/db/migrations/meta/_journal.json | 7 +++++++ apps/api/db/schema.ts | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/api/db/migrations/meta/_journal.json b/apps/api/db/migrations/meta/_journal.json index bd7b0c2d..0795986a 100644 --- a/apps/api/db/migrations/meta/_journal.json +++ b/apps/api/db/migrations/meta/_journal.json @@ -78,6 +78,13 @@ "when": 1716132892106, "tag": "0010_slimy_stature", "breakpoints": true + }, + { + "idx": 11, + "version": "5", + "when": 1733651224111, + "tag": "0011_colorful_sharon_ventura", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/api/db/schema.ts b/apps/api/db/schema.ts index 5a44d263..7d2bcedf 100644 --- a/apps/api/db/schema.ts +++ b/apps/api/db/schema.ts @@ -367,7 +367,6 @@ export const notification = pgTable('notification', { export const userNotification = pgTable( 'user_notification', { - id: serial('id').primaryKey(), userId: integer('user_id') .notNull() .references(() => user.id), From e20b5dfafaa2893c2b5797548354590c0a0cfb2b Mon Sep 17 00:00:00 2001 From: dbaric99 Date: Sun, 8 Dec 2024 12:40:35 +0100 Subject: [PATCH 03/10] Fix typo and add types --- apps/api/db/migrations/meta/_journal.json | 4 +-- apps/api/db/schema.ts | 3 +- packages/types/src/dto/notification.ts | 39 ++++++++++++++++++++++- packages/types/src/enum.ts | 8 +++++ 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/apps/api/db/migrations/meta/_journal.json b/apps/api/db/migrations/meta/_journal.json index 0795986a..8489bfb2 100644 --- a/apps/api/db/migrations/meta/_journal.json +++ b/apps/api/db/migrations/meta/_journal.json @@ -82,8 +82,8 @@ { "idx": 11, "version": "5", - "when": 1733651224111, - "tag": "0011_colorful_sharon_ventura", + "when": 1733654285606, + "tag": "0011_curly_magneto", "breakpoints": true } ] diff --git a/apps/api/db/schema.ts b/apps/api/db/schema.ts index 7d2bcedf..b5299035 100644 --- a/apps/api/db/schema.ts +++ b/apps/api/db/schema.ts @@ -42,7 +42,6 @@ export const surveyQuestionType = pgEnum('survey_question_type', [ 'company', ]); -// new enums export const shopItemType = pgEnum('shop_item_type', [ 'mug', 'shirt', @@ -100,7 +99,7 @@ export const body = pgEnum('body', [ ]); export const notificationType = pgEnum('notification_type', [ - 'announcment', + 'announcement', 'event_reminder', 'achievement', 'emergency', diff --git a/packages/types/src/dto/notification.ts b/packages/types/src/dto/notification.ts index b2ec7ec9..04b4d1ee 100644 --- a/packages/types/src/dto/notification.ts +++ b/packages/types/src/dto/notification.ts @@ -1,17 +1,54 @@ -import { IsOptional, IsString } from 'class-validator'; +import { + IsBoolean, + IsDate, + IsEnum, + IsNumber, + IsOptional, + IsString, +} from 'class-validator'; +import { NotificationType } from 'src/enum'; export type NotificationDto = { id: number; title: string; content?: string; + type: NotificationType; activatedAt?: Date; + expiresAt?: Date; + createdAt?: Date; + createdByUserId?: number; + eventId?: number; + isActive?: boolean; }; export class NotificationModifyDto { @IsString() title: string; + @IsEnum(NotificationType) + type: NotificationType; + @IsOptional() @IsString() content?: string; + + @IsOptional() + @IsDate() + activatedAt?: Date; + + @IsOptional() + @IsDate() + expiresAt?: Date; + + @IsOptional() + @IsNumber() + createdByUserId?: number; + + @IsOptional() + @IsNumber() + eventId?: number; + + @IsOptional() + @IsBoolean() + isActive?: boolean; } diff --git a/packages/types/src/enum.ts b/packages/types/src/enum.ts index c07854e2..3be30b4a 100644 --- a/packages/types/src/enum.ts +++ b/packages/types/src/enum.ts @@ -33,3 +33,11 @@ export enum SurveyQuestionType { Lecture = 'lecture', Company = 'company', } + +export enum NotificationType { + Announcement = 'announcement', + EventReminder = 'event_reminder', + Achievement = 'achievement', + Emergency = 'emergency', + Survey = 'survey', +} From bc22016f118cead1a51adb167d486ca6783b51ea Mon Sep 17 00:00:00 2001 From: dbaric99 Date: Sun, 8 Dec 2024 12:50:27 +0100 Subject: [PATCH 04/10] Fix docker build --- .../src/notification/notification.service.ts | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/apps/api/src/notification/notification.service.ts b/apps/api/src/notification/notification.service.ts index 3cbd49f8..e5034aea 100644 --- a/apps/api/src/notification/notification.service.ts +++ b/apps/api/src/notification/notification.service.ts @@ -1,4 +1,4 @@ -import { NotificationDto, NotificationModifyDto } from '@ddays-app/types'; +import { NotificationModifyDto } from '@ddays-app/types'; import { Injectable } from '@nestjs/common'; import { db } from 'db'; import { notification } from 'db/schema'; @@ -6,7 +6,7 @@ import { desc, eq, lte } from 'drizzle-orm'; @Injectable() export class NotificationService { - async activate(id: number): Promise { + async activate(id: number) { const [activatedNotification] = await db .update(notification) .set({ @@ -18,7 +18,7 @@ export class NotificationService { return activatedNotification; } - async create(dto: NotificationModifyDto): Promise { + async create(dto: NotificationModifyDto) { const [createdNotification] = await db .insert(notification) .values(dto) @@ -27,7 +27,7 @@ export class NotificationService { return createdNotification; } - async deactivate(id: number): Promise { + async deactivate(id: number) { const [deactivatedNotification] = await db .update(notification) .set({ @@ -39,7 +39,7 @@ export class NotificationService { return deactivatedNotification; } - async getActive(): Promise { + async getActive() { const notifications = await db .select({ id: notification.id, @@ -54,7 +54,7 @@ export class NotificationService { return notifications; } - async getAll(): Promise { + async getAll() { const notifications = await db .select({ id: notification.id, @@ -68,7 +68,7 @@ export class NotificationService { return notifications; } - async remove(id: number): Promise { + async remove(id: number) { const [deletedNotification] = await db .delete(notification) .where(eq(notification.id, id)) @@ -77,10 +77,7 @@ export class NotificationService { return deletedNotification; } - async update( - id: number, - dto: NotificationModifyDto, - ): Promise { + async update(id: number, dto: NotificationModifyDto) { const [updatedNotification] = await db .update(notification) .set(dto) From 21bfac5158090707ea6835e180f87c0631bf3d1f Mon Sep 17 00:00:00 2001 From: dbaric99 Date: Sun, 8 Dec 2024 23:22:20 +0100 Subject: [PATCH 05/10] Remove notification type --- apps/api/db/migrations/meta/_journal.json | 7 +++++++ apps/api/db/schema.ts | 10 ---------- .../src/notification/notification.service.ts | 19 +++++++++++-------- packages/types/src/dto/notification.ts | 5 ----- packages/types/src/enum.ts | 8 -------- 5 files changed, 18 insertions(+), 31 deletions(-) diff --git a/apps/api/db/migrations/meta/_journal.json b/apps/api/db/migrations/meta/_journal.json index 8489bfb2..78fb9331 100644 --- a/apps/api/db/migrations/meta/_journal.json +++ b/apps/api/db/migrations/meta/_journal.json @@ -85,6 +85,13 @@ "when": 1733654285606, "tag": "0011_curly_magneto", "breakpoints": true + }, + { + "idx": 12, + "version": "5", + "when": 1733695116615, + "tag": "0012_marvelous_paibok", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/api/db/schema.ts b/apps/api/db/schema.ts index b5299035..4d6000a5 100644 --- a/apps/api/db/schema.ts +++ b/apps/api/db/schema.ts @@ -98,14 +98,6 @@ export const body = pgEnum('body', [ 'dumbell', ]); -export const notificationType = pgEnum('notification_type', [ - 'announcement', - 'event_reminder', - 'achievement', - 'emergency', - 'survey', -]); - export const notificationStatus = pgEnum('notification_status', [ 'pending', 'delivered', @@ -354,7 +346,6 @@ export const notification = pgTable('notification', { id: serial('id').primaryKey(), title: text('title').notNull(), content: text('description'), - type: notificationType('type').notNull(), activatedAt: timestamp('activated_at'), expiresAt: timestamp('expires_at'), createdAt: timestamp('created_at').defaultNow(), @@ -636,7 +627,6 @@ export const notificationTemplate = pgTable('notification_template', { name: text('name').notNull(), titleTemplate: text('title_template').notNull(), contentTemplate: text('content_template').notNull(), - type: notificationType('type').notNull(), createdAt: timestamp('created_at').defaultNow(), }); diff --git a/apps/api/src/notification/notification.service.ts b/apps/api/src/notification/notification.service.ts index e5034aea..3cbd49f8 100644 --- a/apps/api/src/notification/notification.service.ts +++ b/apps/api/src/notification/notification.service.ts @@ -1,4 +1,4 @@ -import { NotificationModifyDto } from '@ddays-app/types'; +import { NotificationDto, NotificationModifyDto } from '@ddays-app/types'; import { Injectable } from '@nestjs/common'; import { db } from 'db'; import { notification } from 'db/schema'; @@ -6,7 +6,7 @@ import { desc, eq, lte } from 'drizzle-orm'; @Injectable() export class NotificationService { - async activate(id: number) { + async activate(id: number): Promise { const [activatedNotification] = await db .update(notification) .set({ @@ -18,7 +18,7 @@ export class NotificationService { return activatedNotification; } - async create(dto: NotificationModifyDto) { + async create(dto: NotificationModifyDto): Promise { const [createdNotification] = await db .insert(notification) .values(dto) @@ -27,7 +27,7 @@ export class NotificationService { return createdNotification; } - async deactivate(id: number) { + async deactivate(id: number): Promise { const [deactivatedNotification] = await db .update(notification) .set({ @@ -39,7 +39,7 @@ export class NotificationService { return deactivatedNotification; } - async getActive() { + async getActive(): Promise { const notifications = await db .select({ id: notification.id, @@ -54,7 +54,7 @@ export class NotificationService { return notifications; } - async getAll() { + async getAll(): Promise { const notifications = await db .select({ id: notification.id, @@ -68,7 +68,7 @@ export class NotificationService { return notifications; } - async remove(id: number) { + async remove(id: number): Promise { const [deletedNotification] = await db .delete(notification) .where(eq(notification.id, id)) @@ -77,7 +77,10 @@ export class NotificationService { return deletedNotification; } - async update(id: number, dto: NotificationModifyDto) { + async update( + id: number, + dto: NotificationModifyDto, + ): Promise { const [updatedNotification] = await db .update(notification) .set(dto) diff --git a/packages/types/src/dto/notification.ts b/packages/types/src/dto/notification.ts index 04b4d1ee..f0f3020b 100644 --- a/packages/types/src/dto/notification.ts +++ b/packages/types/src/dto/notification.ts @@ -6,13 +6,11 @@ import { IsOptional, IsString, } from 'class-validator'; -import { NotificationType } from 'src/enum'; export type NotificationDto = { id: number; title: string; content?: string; - type: NotificationType; activatedAt?: Date; expiresAt?: Date; createdAt?: Date; @@ -25,9 +23,6 @@ export class NotificationModifyDto { @IsString() title: string; - @IsEnum(NotificationType) - type: NotificationType; - @IsOptional() @IsString() content?: string; diff --git a/packages/types/src/enum.ts b/packages/types/src/enum.ts index 3be30b4a..c07854e2 100644 --- a/packages/types/src/enum.ts +++ b/packages/types/src/enum.ts @@ -33,11 +33,3 @@ export enum SurveyQuestionType { Lecture = 'lecture', Company = 'company', } - -export enum NotificationType { - Announcement = 'announcement', - EventReminder = 'event_reminder', - Achievement = 'achievement', - Emergency = 'emergency', - Survey = 'survey', -} From c20f2ce3a572774d4160759680907b573bcac81c Mon Sep 17 00:00:00 2001 From: dbaric99 Date: Mon, 9 Dec 2024 21:31:34 +0100 Subject: [PATCH 06/10] Added language indicator --- apps/api/db/migrations/meta/_journal.json | 7 +++++++ apps/api/db/schema.ts | 1 + 2 files changed, 8 insertions(+) diff --git a/apps/api/db/migrations/meta/_journal.json b/apps/api/db/migrations/meta/_journal.json index 78fb9331..72938eca 100644 --- a/apps/api/db/migrations/meta/_journal.json +++ b/apps/api/db/migrations/meta/_journal.json @@ -92,6 +92,13 @@ "when": 1733695116615, "tag": "0012_marvelous_paibok", "breakpoints": true + }, + { + "idx": 13, + "version": "5", + "when": 1733776204764, + "tag": "0013_premium_menace", + "breakpoints": true } ] } \ No newline at end of file diff --git a/apps/api/db/schema.ts b/apps/api/db/schema.ts index 4d6000a5..3992f7a9 100644 --- a/apps/api/db/schema.ts +++ b/apps/api/db/schema.ts @@ -247,6 +247,7 @@ export const event = pgTable('event', { footageLink: text('footage_link'), maxParticipants: integer('max_participants'), codeId: integer('code_id').references(() => code.id), + isOnEnglish: boolean('is_on_english').default(false), }); export const eventRelations = relations(event, ({ one, many }) => ({ From 94a6ec34f952aa97d1974d4e7ed7f57fa3c15da4 Mon Sep 17 00:00:00 2001 From: dbaric99 Date: Fri, 20 Dec 2024 19:45:56 +0100 Subject: [PATCH 07/10] Fix build --- packages/types/src/dto/speaker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/types/src/dto/speaker.ts b/packages/types/src/dto/speaker.ts index 7619fdca..5830b6ee 100644 --- a/packages/types/src/dto/speaker.ts +++ b/packages/types/src/dto/speaker.ts @@ -7,7 +7,7 @@ export type SpeakerDto = { lastName: string; title: string; companyId?: number; - photo?: string; + photo?: JSON; instagram?: string; linkedin?: string; description?: string; @@ -46,7 +46,7 @@ export type SpeakerWithCompanyDto = { lastName: string; title: string; companyId?: number; - photo?: string; + photo?: JSON; instagram?: string; linkedin?: string; description?: string; From 7cdb364f04498479037b61f9bbb68dd77106124e Mon Sep 17 00:00:00 2001 From: dbaric99 Date: Sun, 22 Dec 2024 18:57:03 +0100 Subject: [PATCH 08/10] Change json dto type --- packages/types/src/dto/speaker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/types/src/dto/speaker.ts b/packages/types/src/dto/speaker.ts index 5830b6ee..279d6148 100644 --- a/packages/types/src/dto/speaker.ts +++ b/packages/types/src/dto/speaker.ts @@ -7,7 +7,7 @@ export type SpeakerDto = { lastName: string; title: string; companyId?: number; - photo?: JSON; + photo?: unknown; instagram?: string; linkedin?: string; description?: string; @@ -46,7 +46,7 @@ export type SpeakerWithCompanyDto = { lastName: string; title: string; companyId?: number; - photo?: JSON; + photo?: unknown; instagram?: string; linkedin?: string; description?: string; From 89832771e0f325cf08cc4cb4d634d7847dbbad41 Mon Sep 17 00:00:00 2001 From: dbaric99 Date: Sun, 22 Dec 2024 22:48:56 +0100 Subject: [PATCH 09/10] Fix build --- apps/admin/src/pages/SpeakerPage.tsx | 2 +- apps/api/db/migrations/meta/_journal.json | 9 ++++++++- apps/api/db/schema.ts | 4 +++- apps/api/src/event/event.service.ts | 3 ++- apps/api/src/speaker/speaker.service.ts | 8 +++++++- packages/types/src/dto/speaker.ts | 9 +++++++-- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/apps/admin/src/pages/SpeakerPage.tsx b/apps/admin/src/pages/SpeakerPage.tsx index 71bf8c10..14eaa5a2 100644 --- a/apps/admin/src/pages/SpeakerPage.tsx +++ b/apps/admin/src/pages/SpeakerPage.tsx @@ -51,7 +51,7 @@ const SpeakerPage = () => { speaker.id === speakerToEditId) - ?.photo + ?.photo?.mainPhotoUrl } handleUpload={handleUpload} handleRemove={handleRemove} diff --git a/apps/api/db/migrations/meta/_journal.json b/apps/api/db/migrations/meta/_journal.json index 77e16193..a1d3dbe3 100644 --- a/apps/api/db/migrations/meta/_journal.json +++ b/apps/api/db/migrations/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1734719722899, "tag": "0000_cold_the_stranger", "breakpoints": true + }, + { + "idx": 1, + "version": "5", + "when": 1734903647949, + "tag": "0001_rich_veda", + "breakpoints": true } ] -} +} \ No newline at end of file diff --git a/apps/api/db/schema.ts b/apps/api/db/schema.ts index 91defea0..e999e6ce 100644 --- a/apps/api/db/schema.ts +++ b/apps/api/db/schema.ts @@ -1,8 +1,10 @@ +import { SpeakerPhoto } from '@ddays-app/types'; import { relations } from 'drizzle-orm'; import { boolean, integer, json, + jsonb, pgEnum, pgTable, primaryKey, @@ -410,7 +412,7 @@ export const speaker = pgTable('speaker', { lastName: text('lastName').notNull(), title: text('title').notNull(), companyId: integer('company_id').references(() => company.id), - photo: json('photo'), + photo: jsonb('photo').$type(), instagram: text('instagram'), linkedin: text('linkedin'), description: text('description'), diff --git a/apps/api/src/event/event.service.ts b/apps/api/src/event/event.service.ts index 8fb4dd96..33e6c9c2 100644 --- a/apps/api/src/event/event.service.ts +++ b/apps/api/src/event/event.service.ts @@ -3,6 +3,7 @@ import { EventDto, EventModifyDto, EventWithSpeakerDto, + SpeakerPhoto, } from '@ddays-app/types'; import { Injectable } from '@nestjs/common'; import { db } from 'db'; @@ -102,7 +103,7 @@ export class EventService { lastName: speaker.lastName, title: speaker.title, companyId: speaker.companyId, - photo: speaker.photo, + photo: speaker.photo as SpeakerPhoto, instagram: speaker.instagram, linkedin: speaker.linkedin, description: speaker.description, diff --git a/apps/api/src/speaker/speaker.service.ts b/apps/api/src/speaker/speaker.service.ts index 45ef3a5a..8abd4d74 100644 --- a/apps/api/src/speaker/speaker.service.ts +++ b/apps/api/src/speaker/speaker.service.ts @@ -1,6 +1,7 @@ import { SpeakerDto, SpeakerModifyDto, + SpeakerPhoto, SpeakerWithCompanyDto, } from '@ddays-app/types'; import { Injectable } from '@nestjs/common'; @@ -115,12 +116,17 @@ export class SpeakerService { id: number, file: Express.Multer.File, ): Promise { - const photo = await this.blobService.upload( + const uploadedPhoto = await this.blobService.upload( 'speaker-photo', file.buffer, file.mimetype, ); + const photo: SpeakerPhoto = { + mainPhotoUrl: uploadedPhoto, + thumbnailUrl: uploadedPhoto, + }; + const [updatedSpeaker] = await db .update(speaker) .set({ diff --git a/packages/types/src/dto/speaker.ts b/packages/types/src/dto/speaker.ts index 279d6148..7b1ee8b5 100644 --- a/packages/types/src/dto/speaker.ts +++ b/packages/types/src/dto/speaker.ts @@ -1,13 +1,18 @@ import { IsNumber, IsOptional, IsString } from 'class-validator'; import { CompanyPublicDto } from './company'; +export type SpeakerPhoto = { + mainPhotoUrl: string; + thumbnailUrl: string; +}; + export type SpeakerDto = { id: number; firstName: string; lastName: string; title: string; companyId?: number; - photo?: unknown; + photo?: SpeakerPhoto; instagram?: string; linkedin?: string; description?: string; @@ -46,7 +51,7 @@ export type SpeakerWithCompanyDto = { lastName: string; title: string; companyId?: number; - photo?: unknown; + photo?: SpeakerPhoto; instagram?: string; linkedin?: string; description?: string; From 39849f6fb4a10a879ec30ee3ccc3ae4125048cff Mon Sep 17 00:00:00 2001 From: dbaric99 Date: Sun, 22 Dec 2024 23:10:34 +0100 Subject: [PATCH 10/10] Fix build --- apps/web/src/components/ScheduleSection/ScheduleCard.tsx | 2 +- apps/web/src/components/SpeakersSection/SpeakerCard.tsx | 2 +- apps/web/src/components/SpeakersSection/SpeakerModal.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/web/src/components/ScheduleSection/ScheduleCard.tsx b/apps/web/src/components/ScheduleSection/ScheduleCard.tsx index 408e93d0..4898391c 100644 --- a/apps/web/src/components/ScheduleSection/ScheduleCard.tsx +++ b/apps/web/src/components/ScheduleSection/ScheduleCard.tsx @@ -34,7 +34,7 @@ const ScheduleCard: React.FC = ({ const imagesList = event.speakers ?.filter((speaker) => speaker.photo !== null) - .map((speaker) => speaker.photo); + .map((speaker) => speaker.photo?.mainPhotoUrl); const images = imagesList?.length === 0 ? [''] : imagesList!; diff --git a/apps/web/src/components/SpeakersSection/SpeakerCard.tsx b/apps/web/src/components/SpeakersSection/SpeakerCard.tsx index 2238db12..16f25634 100644 --- a/apps/web/src/components/SpeakersSection/SpeakerCard.tsx +++ b/apps/web/src/components/SpeakersSection/SpeakerCard.tsx @@ -37,7 +37,7 @@ const SpeakerCard: React.FC = ({ style={{ width: width }} className={c.card} onClick={handleOpenModal}> - +

{speaker.firstName} {speaker.lastName} diff --git a/apps/web/src/components/SpeakersSection/SpeakerModal.tsx b/apps/web/src/components/SpeakersSection/SpeakerModal.tsx index e5db9def..0d492a28 100644 --- a/apps/web/src/components/SpeakersSection/SpeakerModal.tsx +++ b/apps/web/src/components/SpeakersSection/SpeakerModal.tsx @@ -58,7 +58,7 @@ const SpeakerModal: React.FC = ({ onClick={(e) => e.stopPropagation()}> Close
- +