feat: add grammar check functionality and enhance quiz schema

- Introduced a new 'testCheckGrammar' field in DocumentSchema to facilitate grammar checking for documents, leveraging the document service for processing.
- Updated DocumentService to implement grammar checking logic, including caching results and publishing suggestions.
- Enhanced QuizSchema by adding filter arguments for quiz attempts, allowing for more flexible data retrieval based on user and quiz IDs.
- Cleaned up whitespace and improved error handling in quiz attempt creation to ensure better user feedback.

These changes improve the document editing experience and enhance the quiz feature's data handling capabilities.
This commit is contained in:
2024-12-11 22:36:35 +07:00
parent 4168bff1e8
commit 3652fda7d3
7 changed files with 72 additions and 43 deletions

View File

@@ -197,6 +197,16 @@ export class DocumentSchema extends PothosSchema {
}, },
}), }),
testCheckGrammar: t.field({
type: 'Boolean',
resolve: async (_query, _args, ctx: SchemaContext) => {
const documentId = '0a07abe1-4d21-4530-85b9-ed128bfd8f9e'
const pageId = 0
await this.documentService.checkGrammarForPage(documentId, pageId)
return true
},
}),
// exportDocument: t.field({ // exportDocument: t.field({
// type: this.DocumentExportObject(), // type: this.DocumentExportObject(),
// args: { // args: {

View File

@@ -98,51 +98,50 @@ export class DocumentService {
} }
// check grammar for a page by parallely send each sentence to OpenAI service as text and get the result, after that return the result as delta and publish the result to the document // check grammar for a page by parallely send each sentence to OpenAI service as text and get the result, after that return the result as delta and publish the result to the document
// async checkGrammarForPage(documentId: string, pageId: number): Promise<void> { async checkGrammarForPage(documentId: string, pageId: number): Promise<void> {
// const sentenceDelta = await this.pageToSentence(documentId, pageId) const sentenceDelta = await this.pageToSentence(documentId, pageId)
// // Extract the entire page content as a single text // Extract the entire page content as a single text
// const pageText = sentenceDelta.ops const pageText = sentenceDelta.ops
// .filter((op) => typeof op.insert === 'string') .filter((op) => typeof op.insert === 'string')
// .map((op) => op.insert as string) .map((op) => op.insert as string)
// .join(' ') .join(' ')
// // Create a unique cache key for the entire page // Create a unique cache key for the entire page
// const cacheKey = `grammar_check:${documentId}:${pageId}` const cacheKey = `grammar_check:${documentId}:${pageId}`
// // Try to get cached result first // Try to get cached result first
// const cachedResult = await this.redis.get(cacheKey) const cachedResult = await this.redis.get(cacheKey)
// if (cachedResult) { if (cachedResult) {
// Logger.log('Cached grammar check result exists', 'Grammar Check') Logger.log('Cached grammar check result exists', 'Grammar Check')
// return return
// } }
// // Process the entire page text // Process the entire page text
// const grammarCheckResult = await this.openai.processText(pageText, 0, PromptType.CHECK_GRAMMAR) const grammarCheckResult = await this.openai.processText(pageText, 0, PromptType.CHECK_GRAMMAR)
// if (!grammarCheckResult.result) { if (!grammarCheckResult.result) {
// return return
// } }
// // Cache the result // Cache the result
// await this.redis.setPermanent(cacheKey, JSON.stringify(grammarCheckResult)) await this.redis.setPermanent(cacheKey, JSON.stringify(grammarCheckResult))
// // Calculate diff between original page and corrected page // Calculate diff between original page and corrected page
// const diff = await this.diff(pageText, grammarCheckResult.result) const diff = await this.diff(pageText, grammarCheckResult.result)
// // Build payload // Build payload
// Publish the result to the subscriber
// // Publish the result to the subscriber this.pubSub.publish(`${DocumentEvent.AI_SUGGESTION}.${documentId}.${pageId}`, payload)
// this.pubSub.publish(`${DocumentEvent.AI_SUGGESTION}.${documentId}.${pageId}`, payload) }
// }
async diff(original: string, corrected: string): Promise<Delta> {
// async diff(original: string, corrected: string): Promise<Delta> { const originalDelta = new Delta().insert(original)
// const originalDelta = new Delta().insert(original) const correctedDelta = new Delta().insert(corrected)
// const correctedDelta = new Delta().insert(corrected) const diff = originalDelta.diff(correctedDelta)
// const diff = originalDelta.diff(correctedDelta) Logger.log(diff, 'diff')
// Logger.log(diff, 'diff') return diff
// return diff }
// }
} }

View File

@@ -96,6 +96,7 @@ export class PersonalMilestoneSchema extends PothosSchema {
}) })
}, },
}), }),
})) }))
} }
} }

View File

@@ -269,10 +269,18 @@ export class QuizSchema extends PothosSchema {
quizAttempts: t.prismaField({ quizAttempts: t.prismaField({
type: [this.quizAttempt()], type: [this.quizAttempt()],
args: { args: {
filter: t.arg({
type: this.builder.generator.getWhere('QuizAttempt'),
required: false,
}),
quizId: t.arg({ quizId: t.arg({
type: 'String', type: 'String',
required: false, required: false,
}), }),
userId: t.arg({
type: 'String',
required: false,
}),
}, },
resolve: async (query, _root, args, ctx, _info) => { resolve: async (query, _root, args, ctx, _info) => {
if (ctx.isSubscription) { if (ctx.isSubscription) {
@@ -292,10 +300,15 @@ export class QuizSchema extends PothosSchema {
return await this.prisma.quizAttempt.findMany({ return await this.prisma.quizAttempt.findMany({
...query, ...query,
where: { where: {
...args.filter,
quiz: { quiz: {
centerMentorId: centerMentor.mentorId, centerMentorId: centerMentor.mentorId,
}, },
...(args.quizId ? [{ quizId: args.quizId }] : []), ...(args.quizId ? [{ quizId: args.quizId }] : []),
...(args.userId ? [{ quizId: args.userId }] : []),
},
orderBy: {
createdAt: 'desc',
}, },
}) })
} }
@@ -307,6 +320,9 @@ export class QuizSchema extends PothosSchema {
userId: ctx.http.me.id, userId: ctx.http.me.id,
...(args.quizId ? [{ quizId: args.quizId }] : []), ...(args.quizId ? [{ quizId: args.quizId }] : []),
}, },
orderBy: {
createdAt: 'desc',
},
}) })
} }
}, },
@@ -407,6 +423,7 @@ export class QuizSchema extends PothosSchema {
if (!quiz) { if (!quiz) {
throw new Error('Quiz not found') throw new Error('Quiz not found')
} }
try {
return await this.prisma.quizAttempt.create({ return await this.prisma.quizAttempt.create({
...query, ...query,
data: { data: {
@@ -415,6 +432,9 @@ export class QuizSchema extends PothosSchema {
user: { connect: { id: ctx.http.me.id } }, user: { connect: { id: ctx.http.me.id } },
}, },
}) })
} catch (_error) {
throw new Error('Quiz attempt already exists')
}
}, },
}), }),
})) }))

View File

@@ -266,7 +266,6 @@ export class ScheduleSchema extends PothosSchema {
if (!ctx.http?.me?.id) { if (!ctx.http?.me?.id) {
throw new Error('User not found') throw new Error('User not found')
} }
Logger.log(`ctx.http.me.role: ${ctx.http.me.role}`)
// use case 1: customer query schedules where customer is participant // use case 1: customer query schedules where customer is participant
if (ctx.http.me.role === Role.CUSTOMER) { if (ctx.http.me.role === Role.CUSTOMER) {
const schedules = await this.prisma.schedule.findMany({ const schedules = await this.prisma.schedule.findMany({

File diff suppressed because one or more lines are too long