From e00d3aa0ad4e20c6a3c77a2ea93be61a6e42b244 Mon Sep 17 00:00:00 2001 From: Danielzxccc Date: Thu, 2 May 2024 00:15:50 +0800 Subject: [PATCH] farm head chat feature --- src/modules/Forums/ForumsController.ts | 4 ++- src/modules/Forums/ForumsInteractor.ts | 17 ++++++++---- src/modules/Forums/ForumsOpenApi.ts | 5 ++++ src/modules/Forums/ForumsService.ts | 38 ++++++++++++++++---------- src/modules/Socket/SocketController.ts | 4 +++ src/schema/ForumsSchema.ts | 17 +++++++++++- tables/data.sql | 1 + 7 files changed, 64 insertions(+), 22 deletions(-) diff --git a/src/modules/Forums/ForumsController.ts b/src/modules/Forums/ForumsController.ts index 547d8c8..b9375c0 100644 --- a/src/modules/Forums/ForumsController.ts +++ b/src/modules/Forums/ForumsController.ts @@ -49,6 +49,7 @@ export async function listQuestions(req: SessionRequest, res: Response) { const searchKey = String(query.search) const filterKey = query.filter const tagKey = query.tag + const privateForum = query.privateForum const questions = await Interactor.listQuestions( offset, @@ -57,7 +58,8 @@ export async function listQuestions(req: SessionRequest, res: Response) { perPage, req.session.userid || '00', query.profile, - tagKey + tagKey, + privateForum ) const totalPages = Math.ceil(Number(questions.total.count) / perPage) res.status(200).json({ diff --git a/src/modules/Forums/ForumsInteractor.ts b/src/modules/Forums/ForumsInteractor.ts index 37444bd..f064e11 100644 --- a/src/modules/Forums/ForumsInteractor.ts +++ b/src/modules/Forums/ForumsInteractor.ts @@ -19,6 +19,7 @@ import { deleteFile } from '../../utils/file' import { viewsLimitter } from '../../middleware/ViewsLimitter' import { findUser } from '../Users/UserService' import { emitPushNotification } from '../Notifications/NotificationInteractor' +import { emitNotificationToFarmHeads } from '../Socket/SocketController' export async function viewQuestion( id: string, @@ -66,7 +67,8 @@ export async function listQuestions( perpage: number, userid: string, profile?: string, - tag?: string + tag?: string, + privateForum?: boolean ) { const [data, total] = await Promise.all([ Service.findQuestions( @@ -76,9 +78,10 @@ export async function listQuestions( perpage, userid, profile, - tag + tag, + privateForum ), - Service.getTotalCount(profile, searchKey, tag), + Service.getTotalCount(profile, searchKey, tag, privateForum), ]) for (let question of data) { @@ -131,10 +134,14 @@ export async function createNewQuestion( if (!userid) { throw new HttpError('Session Expired', 401) } - const { title, question, tags } = questions.body - const content = { userid, title, question, imagesrc } + const { title, question, tags, privateForum } = questions.body + const content = { userid, title, question, imagesrc, private: privateForum } const newQuestion = await Service.createQuestion(content, tags) + if (newQuestion.private) { + emitNotificationToFarmHeads() + } + await uploadFiles(uploadedFiles) for (const image of uploadedFiles) { deleteFile(image.filename) diff --git a/src/modules/Forums/ForumsOpenApi.ts b/src/modules/Forums/ForumsOpenApi.ts index 56c6f89..dda4dbd 100644 --- a/src/modules/Forums/ForumsOpenApi.ts +++ b/src/modules/Forums/ForumsOpenApi.ts @@ -40,6 +40,11 @@ * schema: * type: string * description: tag query + * - in: query + * name: privateForum + * schema: + * type: boolean + * description: tag query * responses: * "200": * description: Success diff --git a/src/modules/Forums/ForumsService.ts b/src/modules/Forums/ForumsService.ts index 37cc1e9..e2f2630 100644 --- a/src/modules/Forums/ForumsService.ts +++ b/src/modules/Forums/ForumsService.ts @@ -27,7 +27,8 @@ export async function findQuestions( perpage: number, userid: string, profile?: string, - tag?: string + tag?: string, + privateForum?: boolean ) { let query = db .selectFrom('forums') @@ -38,14 +39,17 @@ export async function findQuestions( 'forums.id', jsonObjectFrom( eb - .selectFrom('users') + .selectFrom('users as u') + .leftJoin('community_farms as cf', 'cf.id', 'u.farm_id') .select([ - 'avatar', - 'username', - 'role', - sql`CAST(id AS TEXT)`.as('id'), + 'u.avatar', + 'u.username', + 'u.role', + 'u.district', + 'cf.farm_name', + sql`CAST(u.id AS TEXT)`.as('id'), ]) - .whereRef('forums.userid', '=', 'users.id') + .whereRef('forums.userid', '=', 'u.id') ).as('user'), jsonArrayFrom( eb @@ -63,11 +67,6 @@ export async function findQuestions( 'forums.updatedat', 'forums.views', sql`COUNT(DISTINCT forums_answers.id)`.as('answer_count'), - // fn - // .count('forums_ratings.id') - // .filterWhere('type', '=', 'upvote') - // .distinct() - // .as('vote_count'), fn.count('forums_ratings.id').distinct().as('vote_count'), fn .count('forums_ratings.id') @@ -79,8 +78,6 @@ export async function findQuestions( .distinct() .filterWhere('type', '=', 'upvote') .as('upvote'), - // fn.count('DISTINCT forums_answers.id').as('answer_count'), - // fn.count('forums_ratings.id').as('vote_count'), fn.max('forums_answers.createdat').as('latest_answer_createdat'), jsonObjectFrom( eb @@ -99,6 +96,12 @@ export async function findQuestions( query = query.orderBy('latest_answer_createdat', 'desc') if (filterKey === 'trending') query = query.orderBy('upvote', 'desc') + if (privateForum) { + query = query.where('forums.private', '=', true) + } else { + query = query.where('forums.private', '=', false) + } + if (searchQuery.length) { query = query.where((eb) => eb.or([ @@ -369,7 +372,8 @@ export async function getTotalAnswers(id: string) { export async function getTotalCount( id: string, searchKey: string, - tag?: string + tag?: string, + privateForum?: boolean ) { let query = db .selectFrom('forums') @@ -387,6 +391,10 @@ export async function getTotalCount( ) } + if (privateForum) { + query = query.where('forums.private', '=', true) + } + if (tag.length) { query = query.where(({ selectFrom, exists }) => exists( diff --git a/src/modules/Socket/SocketController.ts b/src/modules/Socket/SocketController.ts index ecc5ae7..aacb1aa 100644 --- a/src/modules/Socket/SocketController.ts +++ b/src/modules/Socket/SocketController.ts @@ -23,3 +23,7 @@ export function emitNotification(id: string, payload: string) { export function emitNotificationToAdmin(payload: string) { io.emit('admin', payload) } + +export function emitNotificationToFarmHeads() { + io.emit('farm_head', 'CHAT_EVENT_TRIGGER') +} diff --git a/src/schema/ForumsSchema.ts b/src/schema/ForumsSchema.ts index 4d3a166..e15d708 100644 --- a/src/schema/ForumsSchema.ts +++ b/src/schema/ForumsSchema.ts @@ -25,6 +25,10 @@ import { z } from 'zod' * type: string * role: * type: string + * district: + * type: string + * farm_name: + * type: string * tags: * type: array * items: @@ -79,7 +83,6 @@ import { z } from 'zod' * required: * - title * - question - * - imagesrc * properties: * title: * type: string @@ -87,6 +90,9 @@ import { z } from 'zod' * question: * type: string * description: The question in the forum entry + * privateForum: + * type: boolean + * description: The question in the forum entry * imagesrc: * type: array * items: @@ -292,6 +298,11 @@ export const SearchForums = z.object({ filter: z.string().optional().default('newest'), profile: z.string().optional().default(''), tag: z.string().optional().default(''), + privateForum: z + .string() + .transform((arg) => Boolean(arg)) + .optional() + .default(''), }), }) /** @@ -346,6 +357,10 @@ export const ForumsSchema = z.object({ question: z .string({ required_error: 'Question is required' }) .min(1, 'Question must not be empty'), + privateForum: z + .string() + .transform((arg) => Boolean(arg)) + .optional(), tags: z.union([z.array(z.string()), z.string()]).optional(), }), }) diff --git a/tables/data.sql b/tables/data.sql index 878d3d9..beedcfa 100644 --- a/tables/data.sql +++ b/tables/data.sql @@ -196,6 +196,7 @@ CREATE TABLE forums( question TEXT NOT NULL, views INT DEFAULT 0, imagesrc TEXT[], + private BOOLEAN default false, createdAt timestamp DEFAULT CURRENT_TIMESTAMP, updatedAt timestamp DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (userid) REFERENCES users(id) ON DELETE CASCADE