feat: add search and rich collaboration requests
فشلت بعض الفحوصات
Deploy To Ghaymah / deploy (push) Has been cancelled

هذا الالتزام موجود في:
boutmoun123
2026-06-03 23:36:31 +03:00
الأصل 637782aed6
التزام 768b84772b
14 ملفات معدلة مع 12072 إضافات و10597 حذوفات

عرض الملف

@@ -1,4 +1,9 @@
import { BadRequestException, ForbiddenException, Injectable, NotFoundException } from '@nestjs/common';
import {
BadRequestException,
ForbiddenException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model, Types } from 'mongoose';
import { PaginationQueryDto } from '../../common/dto/pagination-query.dto';
@@ -7,6 +12,7 @@ import { BlocksRepository } from '../blocks/blocks.repository';
import { NotificationsService } from '../notifications/notifications.service';
import { PostsRepository } from '../posts/posts.repository';
import { UsersRepository } from '../users/users.repository';
import { CreateCollaborationRequestDto } from './dto/create-collaboration-request.dto';
import {
CollaborationRequest,
CollaborationRequestDocument,
@@ -23,7 +29,8 @@ export class CollaborationRequestsService {
private readonly notificationsService: NotificationsService,
) {}
async create(requesterId: string, postId: string, targetUserId: string) {
async create(requesterId: string, postId: string, dto: CreateCollaborationRequestDto) {
const targetUserId = dto.targetUserId;
if (!Types.ObjectId.isValid(postId) || !Types.ObjectId.isValid(targetUserId)) {
throw new BadRequestException('Invalid collaboration request');
}
@@ -55,21 +62,25 @@ export class CollaborationRequestsService {
targetUserId: new Types.ObjectId(targetUserId),
status: 'pending',
};
const collaborationDetails = this.buildCollaborationDetails(dto);
const existing = await this.collaborationRequestModel.findOne(filter).exec();
const request = existing ?? await this.collaborationRequestModel
.findOneAndUpdate(
filter,
{
$setOnInsert: {
postId: new Types.ObjectId(postId),
requesterId: new Types.ObjectId(requesterId),
targetUserId: new Types.ObjectId(targetUserId),
status: 'pending',
},
},
{ new: true, upsert: true, setDefaultsOnInsert: true },
)
.exec();
const request = existing
? await this.updateExistingPendingRequest(existing.id, collaborationDetails)
: await this.collaborationRequestModel
.findOneAndUpdate(
filter,
{
$setOnInsert: {
postId: new Types.ObjectId(postId),
requesterId: new Types.ObjectId(requesterId),
targetUserId: new Types.ObjectId(targetUserId),
status: 'pending',
...collaborationDetails,
},
},
{ new: true, upsert: true, setDefaultsOnInsert: true },
)
.exec();
if (!existing) {
await this.notificationsService.create({
@@ -79,6 +90,7 @@ export class CollaborationRequestsService {
referenceId: postId,
resourceType: 'post',
deepLink: `/posts/${postId}`,
metadata: collaborationDetails,
});
}
@@ -93,7 +105,10 @@ export class CollaborationRequestsService {
const [items, total] = await Promise.all([
this.collaborationRequestModel
.find(filter)
.populate({ path: 'requesterId', select: 'name username stageName avatar isVerified isDisabled' })
.populate({
path: 'requesterId',
select: 'name username stageName avatar isVerified isDisabled',
})
.populate({ path: 'postId' })
.sort({ createdAt: -1 })
.skip(skip)
@@ -117,13 +132,43 @@ export class CollaborationRequestsService {
return { rejected: true, request };
}
private async updateStatus(targetUserId: string, requestId: string, status: 'approved' | 'rejected') {
private buildCollaborationDetails(dto: CreateCollaborationRequestDto) {
return {
...(dto.collaborationType ? { collaborationType: dto.collaborationType } : {}),
...(typeof dto.message === 'string' ? { message: dto.message.trim() } : {}),
...(typeof dto.attachmentUrl === 'string' ? { attachmentUrl: dto.attachmentUrl.trim() } : {}),
...(dto.attachmentType ? { attachmentType: dto.attachmentType } : {}),
};
}
private async updateExistingPendingRequest(
requestId: string,
collaborationDetails: Record<string, unknown>,
) {
if (!Object.keys(collaborationDetails).length) {
return this.collaborationRequestModel.findById(requestId).exec();
}
return this.collaborationRequestModel
.findByIdAndUpdate(requestId, { $set: collaborationDetails }, { new: true })
.exec();
}
private async updateStatus(
targetUserId: string,
requestId: string,
status: 'approved' | 'rejected',
) {
if (!Types.ObjectId.isValid(requestId)) {
throw new BadRequestException('Invalid collaboration request id');
}
const request = await this.collaborationRequestModel
.findOneAndUpdate(
{ _id: new Types.ObjectId(requestId), targetUserId: new Types.ObjectId(targetUserId), status: 'pending' },
{
_id: new Types.ObjectId(requestId),
targetUserId: new Types.ObjectId(targetUserId),
status: 'pending',
},
{ status },
{ new: true },
)