Refactor Category and Center schemas to improve field descriptions and code clarity; update email templates for consistency in messaging. Add Redis service to CenterSchema for session management. Bump epess-database subproject commit reference to indicate changes. Clean up logging in ClerkService and ServiceSchema.
This commit is contained in:
@@ -1,10 +1,5 @@
|
||||
import { Inject, Injectable } from '@nestjs/common'
|
||||
import {
|
||||
Pothos,
|
||||
PothosRef,
|
||||
PothosSchema,
|
||||
SchemaBuilderToken,
|
||||
} from '@smatch-corp/nestjs-pothos'
|
||||
import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'
|
||||
import { Builder } from '../Graphql/graphql.builder'
|
||||
import { PrismaService } from '../Prisma/prisma.service'
|
||||
|
||||
@@ -28,6 +23,9 @@ export class CategorySchema extends PothosSchema {
|
||||
name: t.exposeString('name', {
|
||||
description: 'The name of the category.',
|
||||
}),
|
||||
description: t.exposeString('description', {
|
||||
description: 'The description of the category.',
|
||||
}),
|
||||
subCategory: t.relation('subCategory', {
|
||||
description: 'The subcategory of the category.',
|
||||
}),
|
||||
@@ -46,16 +44,17 @@ export class CategorySchema extends PothosSchema {
|
||||
name: t.exposeString('name', {
|
||||
description: 'The name of the subcategory.',
|
||||
}),
|
||||
description: t.exposeString('description', {
|
||||
description: 'The description of the subcategory.',
|
||||
}),
|
||||
categoryId: t.exposeID('categoryId', {
|
||||
description:
|
||||
'The ID of the category that the subcategory belongs to.',
|
||||
description: 'The ID of the category that the subcategory belongs to.',
|
||||
}),
|
||||
category: t.relation('category', {
|
||||
description: 'The category that the subcategory belongs to.',
|
||||
}),
|
||||
serviceAndCategory: t.relation('serviceAndCategory', {
|
||||
description:
|
||||
'The service and category that the subcategory belongs to.',
|
||||
description: 'The service and category that the subcategory belongs to.',
|
||||
}),
|
||||
}),
|
||||
})
|
||||
@@ -65,8 +64,7 @@ export class CategorySchema extends PothosSchema {
|
||||
init(): void {
|
||||
this.builder.queryFields((t) => ({
|
||||
categories: t.prismaField({
|
||||
description:
|
||||
'Retrieve a list of categories with optional filtering, ordering, and pagination.',
|
||||
description: 'Retrieve a list of categories with optional filtering, ordering, and pagination.',
|
||||
type: [this.category()],
|
||||
args: this.builder.generator.findManyArgs('Category'),
|
||||
resolve: async (query, _root, args) => {
|
||||
@@ -91,8 +89,7 @@ export class CategorySchema extends PothosSchema {
|
||||
},
|
||||
}),
|
||||
subCategories: t.prismaField({
|
||||
description:
|
||||
'Retrieve a list of subcategories with optional filtering, ordering, and pagination.',
|
||||
description: 'Retrieve a list of subcategories with optional filtering, ordering, and pagination.',
|
||||
type: [this.subCategory()],
|
||||
args: this.builder.generator.findManyArgs('SubCategory'),
|
||||
resolve: async (query, _root, args) => {
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import {Inject, Injectable, Logger} from '@nestjs/common'
|
||||
import {
|
||||
Pothos,
|
||||
PothosRef,
|
||||
PothosSchema,
|
||||
SchemaBuilderToken,
|
||||
} from '@smatch-corp/nestjs-pothos'
|
||||
import {Builder} from '../Graphql/graphql.builder'
|
||||
import {PrismaService} from '../Prisma/prisma.service'
|
||||
import {MinioService} from '../Minio/minio.service'
|
||||
import {CenterStatus, Role} from '@prisma/client'
|
||||
import {MailService} from '../Mail/mail.service'
|
||||
import { Inject, Injectable, Logger } from '@nestjs/common'
|
||||
import { Pothos, PothosRef, PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos'
|
||||
import { Builder } from '../Graphql/graphql.builder'
|
||||
import { PrismaService } from '../Prisma/prisma.service'
|
||||
import { MinioService } from '../Minio/minio.service'
|
||||
import { CenterStatus, Role } from '@prisma/client'
|
||||
import { MailService } from '../Mail/mail.service'
|
||||
import { clerkClient } from '@clerk/express'
|
||||
import { RedisService } from 'src/Redis/redis.service'
|
||||
|
||||
@Injectable()
|
||||
export class CenterSchema extends PothosSchema {
|
||||
@@ -18,6 +15,7 @@ export class CenterSchema extends PothosSchema {
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly minioService: MinioService,
|
||||
private readonly mailService: MailService,
|
||||
private readonly redisService: RedisService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
@@ -54,11 +52,7 @@ export class CenterSchema extends PothosSchema {
|
||||
resolve: async (center) => {
|
||||
// get file id from logoUrl
|
||||
const logoFileId = center.logoUrl?.split('/').pop()?.split('?')[0]
|
||||
return await this.minioService.updatePresignUrl(
|
||||
logoFileId ?? '',
|
||||
'files',
|
||||
center.logoUrl ?? undefined,
|
||||
)
|
||||
return await this.minioService.updatePresignUrl(logoFileId ?? '', 'files', center.logoUrl ?? undefined)
|
||||
},
|
||||
}),
|
||||
logoFile: t.relation('logoFile', {
|
||||
@@ -71,8 +65,8 @@ export class CenterSchema extends PothosSchema {
|
||||
nullable: true,
|
||||
description: 'Whether the center is an individual center.',
|
||||
}),
|
||||
createdAt: t.expose('createdAt', {type: 'DateTime'}),
|
||||
updatedAt: t.expose('updatedAt', {type: 'DateTime'}),
|
||||
createdAt: t.expose('createdAt', { type: 'DateTime' }),
|
||||
updatedAt: t.expose('updatedAt', { type: 'DateTime' }),
|
||||
services: t.relation('services', {
|
||||
description: 'The services provided by the center.',
|
||||
}),
|
||||
@@ -103,8 +97,7 @@ export class CenterSchema extends PothosSchema {
|
||||
init(): void {
|
||||
this.builder.queryFields((t) => ({
|
||||
centers: t.prismaField({
|
||||
description:
|
||||
'Retrieve a list of centers with optional filtering, ordering, and pagination.',
|
||||
description: 'Retrieve a list of centers with optional filtering, ordering, and pagination.',
|
||||
type: [this.center()],
|
||||
args: this.builder.generator.findManyArgs('Center'),
|
||||
resolve: async (query, _root, args) => {
|
||||
@@ -133,7 +126,7 @@ export class CenterSchema extends PothosSchema {
|
||||
type: this.center(),
|
||||
description: 'Retrieve a single center by its unique identifier.',
|
||||
args: {
|
||||
userId: t.arg({type: 'String', required: true}),
|
||||
userId: t.arg({ type: 'String', required: true }),
|
||||
},
|
||||
resolve: async (_query, _root, args) => {
|
||||
return await this.prisma.center.findFirst({
|
||||
@@ -221,8 +214,14 @@ export class CenterSchema extends PothosSchema {
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
resolve: async (query, _root, args) => {
|
||||
resolve: async (query, _root, args, ctx) => {
|
||||
return await this.prisma.$transaction(async (prisma) => {
|
||||
if (ctx.isSubscription) {
|
||||
throw new Error('Not allowed in subscription')
|
||||
}
|
||||
if (ctx.http.me?.role !== Role.ADMIN && ctx.http.me?.role !== Role.MODERATOR) {
|
||||
throw new Error('Not allowed')
|
||||
}
|
||||
const center = await prisma.center.findUnique({
|
||||
...query,
|
||||
where: {
|
||||
@@ -249,6 +248,14 @@ export class CenterSchema extends PothosSchema {
|
||||
if (!centerOwner) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
// get active clerk session and invalidate cache
|
||||
const sessionList = await clerkClient.sessions.getSessionList({
|
||||
userId: centerOwnerId,
|
||||
})
|
||||
// clear all session cache in redis
|
||||
sessionList.data.forEach(async (session) => {
|
||||
await this.redisService.del(session.id)
|
||||
})
|
||||
await prisma.user.update({
|
||||
where: {
|
||||
id: centerOwnerId,
|
||||
@@ -257,6 +264,7 @@ export class CenterSchema extends PothosSchema {
|
||||
role: Role.CENTER_OWNER,
|
||||
},
|
||||
})
|
||||
|
||||
// update center status
|
||||
const updatedCenter = await prisma.center.update({
|
||||
...query,
|
||||
@@ -264,9 +272,7 @@ export class CenterSchema extends PothosSchema {
|
||||
id: args.centerId,
|
||||
},
|
||||
data: {
|
||||
centerStatus: args.approve
|
||||
? CenterStatus.APPROVED
|
||||
: CenterStatus.REJECTED,
|
||||
centerStatus: args.approve ? CenterStatus.APPROVED : CenterStatus.REJECTED,
|
||||
},
|
||||
})
|
||||
// mail to center owner if approved
|
||||
|
||||
@@ -24,11 +24,10 @@ export class ClerkService {
|
||||
// session.removed
|
||||
// session.ended
|
||||
// email.created
|
||||
console.log(eventType, data)
|
||||
Logger.log(eventType, data, 'ClerkService')
|
||||
if (eventType === 'user.created') {
|
||||
this.eventUserCreated(data)
|
||||
}
|
||||
|
||||
if (eventType === 'user.updated') {
|
||||
this.eventUserUpdated(data)
|
||||
}
|
||||
@@ -57,7 +56,6 @@ export class ClerkService {
|
||||
const primary_email_address_id = data.primary_email_address_id
|
||||
// get primary email address on email_addresses by querying email_addresses with primary_email_address_id
|
||||
let primary_email_address = data.email_addresses.find((email: any) => email.id === primary_email_address_id)
|
||||
console.log(primary_email_address)
|
||||
if (!primary_email_address) {
|
||||
primary_email_address = ''
|
||||
}
|
||||
@@ -87,7 +85,6 @@ export class ClerkService {
|
||||
}
|
||||
|
||||
async eventUserUpdated(data: any) {
|
||||
console.log(data)
|
||||
const user_id = data.id
|
||||
const name = `${data.first_name} ${data.last_name}`
|
||||
await this.prisma.user.update({
|
||||
@@ -97,7 +94,6 @@ export class ClerkService {
|
||||
}
|
||||
|
||||
async eventSessionCreated(data: any) {
|
||||
console.log(data)
|
||||
// check if user exists in database or create user
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: data.user_id },
|
||||
@@ -105,7 +101,6 @@ export class ClerkService {
|
||||
if (!user) {
|
||||
// get user info from clerk
|
||||
const userInfo = await clerkClient.users.getUser(data.user_id)
|
||||
console.log(userInfo)
|
||||
try {
|
||||
await this.prisma.user.create({
|
||||
data: {
|
||||
@@ -123,18 +118,18 @@ export class ClerkService {
|
||||
}
|
||||
|
||||
eventSessionRevoked(data: any) {
|
||||
console.log(data)
|
||||
Logger.log(data, 'ClerkService')
|
||||
}
|
||||
|
||||
eventSessionRemoved(data: any) {
|
||||
console.log(data)
|
||||
Logger.log(data, 'ClerkService')
|
||||
}
|
||||
|
||||
eventSessionEnded(data: any) {
|
||||
console.log(data)
|
||||
Logger.log(data, 'ClerkService')
|
||||
}
|
||||
|
||||
eventEmailCreated(data: any) {
|
||||
console.log(data)
|
||||
Logger.log(data, 'ClerkService')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ html
|
||||
body
|
||||
.container
|
||||
.header
|
||||
h1 Chúc mừng Trung tâm #{CENTER_NAME} đã được phê duyệt
|
||||
h1 Chúc mừng #{CENTER_NAME} đã được phê duyệt
|
||||
.content
|
||||
p Kính gửi Quý Trung tâm,
|
||||
p Chúng tôi vui mừng thông báo rằng trung tâm #{CENTER_NAME} của bạn đã được phê duyệt trên nền tảng của chúng tôi.
|
||||
|
||||
@@ -67,7 +67,7 @@ html
|
||||
body
|
||||
.container
|
||||
.header
|
||||
h1 Thông báo từ chối Trung tâm #{CENTER_NAME}
|
||||
h1 Thông báo từ chối #{CENTER_NAME}
|
||||
.content
|
||||
p Kính gửi Quý Trung tâm,
|
||||
p Chúng tôi rất tiếc thông báo rằng trung tâm #{CENTER_NAME} của bạn chưa được phê duyệt trên nền tảng của chúng tôi.
|
||||
|
||||
@@ -59,10 +59,10 @@ html
|
||||
body
|
||||
.container
|
||||
.header
|
||||
h1 Thư mời làm việc từ Trung tâm #{center_name}
|
||||
h1 Thư mời làm việc từ #{center_name}
|
||||
.content
|
||||
p Chào bạn,
|
||||
p Chúng tôi rất vui mừng thông báo rằng bạn đã được mời làm người hướng dẫn tại trung tâm #{center_name}.
|
||||
p Chúng tôi rất vui mừng thông báo rằng bạn đã được mời làm người hướng dẫn tại #{center_name}.
|
||||
p Để tiếp tục quá trình ứng tuyển, vui lòng nhấn vào nút dưới đây để truy cập vào trang nộp resume của bạn.
|
||||
a.button(href=invite_url) Nộp Resume
|
||||
p Nếu bạn có bất kỳ thắc mắc nào, đừng ngần ngại liên hệ với chúng tôi.
|
||||
|
||||
@@ -62,7 +62,7 @@ html
|
||||
h1 Thông báo kết quả ứng tuyển của #{USER_NAME} tại #{CENTER_NAME}
|
||||
.content
|
||||
p Chào #{USER_NAME},
|
||||
p Chúng tôi rất tiếc thông báo rằng bạn chưa được phê duyệt trở thành Mentor tại trung tâm #{CENTER_NAME} lần này.
|
||||
p Chúng tôi rất tiếc thông báo rằng bạn chưa được phê duyệt trở thành Mentor tại #{CENTER_NAME} lần này.
|
||||
p Chúng tôi khuyến khích bạn tiếp tục nâng cao kỹ năng và kinh nghiệm, và mong đợi đơn ứng tuyển của bạn trong tương lai.
|
||||
p Bạn có thể truy cập trang web của chúng tôi để biết thêm thông tin:
|
||||
a.button(href="https://center.epess.org") Truy cập Trung tâm
|
||||
|
||||
@@ -61,7 +61,7 @@ html
|
||||
.header
|
||||
h1 Chúc mừng Dịch vụ #{SERVICE_NAME} đã được phê duyệt
|
||||
.content
|
||||
p Kính gửi Quý Trung tâm #{CENTER_NAME},
|
||||
p Kính gửi #{CENTER_NAME},
|
||||
p Chúng tôi vui mừng thông báo rằng dịch vụ #{SERVICE_NAME} của bạn đã được phê duyệt trên nền tảng của chúng tôi.
|
||||
p Vui lòng nhấn vào nút dưới đây để truy cập vào dịch vụ của bạn:
|
||||
a.button(href="https://center.epess.org") Truy cập Dịch vụ
|
||||
|
||||
@@ -69,7 +69,7 @@ html
|
||||
.header
|
||||
h1 Thông báo từ chối Dịch vụ #{SERVICE_NAME}
|
||||
.content
|
||||
p Kính gửi Quý Trung tâm #{CENTER_NAME},
|
||||
p Kính gửi #{CENTER_NAME},
|
||||
p Chúng tôi rất tiếc thông báo rằng dịch vụ #{SERVICE_NAME} của bạn chưa được phê duyệt trên nền tảng của chúng tôi.
|
||||
.note
|
||||
p Lý do từ chối:
|
||||
|
||||
@@ -364,7 +364,6 @@ export class ServiceSchema extends PothosSchema {
|
||||
const mentorEmails = await prisma.user.findMany({
|
||||
where: { id: { in: mentorIds } },
|
||||
})
|
||||
Logger.log(mentorEmails, 'ServiceSchema')
|
||||
const emails = [centerOwner.email, ...mentorEmails.map((mentor) => mentor.email)]
|
||||
if (args.approve) {
|
||||
await this.mailService.sendTemplateEmail(emails, 'Thông báo về trạng thái dịch vụ', 'ServiceApproved', {
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user