mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-14 09:57:28 +00:00
add subspace controller
This commit is contained in:
@ -129,4 +129,30 @@ export class ControllerRoute {
|
||||
'Disassociates a user from a space by removing the existing association.';
|
||||
};
|
||||
};
|
||||
|
||||
static SUBSPACE = class {
|
||||
public static readonly ROUTE =
|
||||
'/communities/:communityUuid/spaces/:spaceUuid/subspaces';
|
||||
static ACTIONS = class {
|
||||
public static readonly CREATE_SUBSPACE_SUMMARY = 'Create Subspace';
|
||||
public static readonly CREATE_SUBSPACE_DESCRIPTION =
|
||||
'Creates a new subspace within a specific space and community.';
|
||||
|
||||
public static readonly LIST_SUBSPACES_SUMMARY = 'List Subspaces';
|
||||
public static readonly LIST_SUBSPACES_DESCRIPTION =
|
||||
'Retrieves a list of subspaces within a specified space and community.';
|
||||
|
||||
public static readonly GET_SUBSPACE_SUMMARY = 'Get Subspace';
|
||||
public static readonly GET_SUBSPACE_DESCRIPTION =
|
||||
'Fetches a specific subspace by UUID within a given space and community';
|
||||
|
||||
public static readonly UPDATE_SUBSPACE_SUMMARY = 'Update Subspace';
|
||||
public static readonly UPDATE_SUBSPACE_DESCRIPTION =
|
||||
'Updates a specific subspace within a given space and community.';
|
||||
|
||||
public static readonly DELETE_SUBSPACE_SUMMARY = 'Delete Subspace';
|
||||
public static readonly DELETE_SUBSPACE_DESCRIPTION =
|
||||
'Deletes a specific subspace within a given space and community.';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -15,9 +15,6 @@ export class SpacePermissionService {
|
||||
const spaceData = await this.spaceRepository.findOne({
|
||||
where: {
|
||||
uuid: spaceUuid,
|
||||
spaceType: {
|
||||
type: type,
|
||||
},
|
||||
userSpaces: {
|
||||
user: {
|
||||
uuid: userUuid,
|
||||
|
@ -97,7 +97,7 @@ export function TypeORMCustomModel(repository: Repository<any>) {
|
||||
|
||||
// Use the where clause directly, without wrapping it under 'where'
|
||||
const whereClause = buildTypeORMWhereClause({ where });
|
||||
console.log('Where clause after building:', whereClause);
|
||||
console.log('Final where clause:', whereClause);
|
||||
|
||||
// Ensure the whereClause is passed directly to findAndCount
|
||||
const [data, count] = await repository.findAndCount({
|
||||
@ -112,7 +112,7 @@ export function TypeORMCustomModel(repository: Repository<any>) {
|
||||
const paginationResponseDto = getPaginationResponseDto(count, page, size);
|
||||
const baseResponseDto: BaseResponseDto = {
|
||||
data,
|
||||
message: getResponseMessage(modelName, { where: whereClause }),
|
||||
message: getResponseMessage(modelName, { where }),
|
||||
};
|
||||
|
||||
return { baseResponseDto, paginationResponseDto };
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { SpaceEntity, SpaceTypeEntity } from '../entities';
|
||||
import { SpaceEntity, SpaceTypeEntity, SubspaceEntity } from '../entities';
|
||||
|
||||
@Injectable()
|
||||
export class SpaceRepository extends Repository<SpaceEntity> {
|
||||
@ -15,3 +15,10 @@ export class SpaceTypeRepository extends Repository<SpaceTypeEntity> {
|
||||
super(SpaceTypeEntity, dataSource.createEntityManager());
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class SubspaceRepository extends Repository<SubspaceEntity> {
|
||||
constructor(private dataSource: DataSource) {
|
||||
super(SubspaceEntity, dataSource.createEntityManager());
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,9 @@ const mappingInclude: { [key: string]: any } = {
|
||||
space: {
|
||||
space: true,
|
||||
},
|
||||
subspace: {
|
||||
subspace: true,
|
||||
},
|
||||
};
|
||||
|
||||
export function buildTypeORMIncludeQuery(
|
||||
|
@ -1,10 +1,29 @@
|
||||
import { FindOptionsWhere } from 'typeorm';
|
||||
|
||||
export function buildTypeORMWhereClause({
|
||||
where,
|
||||
}: {
|
||||
where?: FindOptionsWhere<any> | FindOptionsWhere<any>[]; // Accepts both object and array formats
|
||||
}): FindOptionsWhere<any> | FindOptionsWhere<any>[] {
|
||||
// Return the 'where' clause directly, without wrapping
|
||||
return where || {}; // If 'where' is undefined, return an empty object
|
||||
export function buildTypeORMWhereClause({ where }) {
|
||||
if (!where) return {};
|
||||
|
||||
// Remove extra nesting if `where` is wrapped within an additional `where` property
|
||||
const condition = where.where ? where.where : where;
|
||||
|
||||
console.log(condition);
|
||||
const convertToNestedObject = (condition: any): any => {
|
||||
const result = {};
|
||||
for (const [key, value] of Object.entries(condition)) {
|
||||
if (key.includes('.')) {
|
||||
const [parentKey, childKey] = key.split('.');
|
||||
result[parentKey] = {
|
||||
...(result[parentKey] || {}),
|
||||
[childKey]: value,
|
||||
};
|
||||
} else {
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
return Array.isArray(condition)
|
||||
? condition.map((item) => convertToNestedObject(item))
|
||||
: convertToNestedObject(condition);
|
||||
}
|
||||
|
@ -1,2 +1,3 @@
|
||||
export * from './space.controller';
|
||||
export * from './space-user.controller';
|
||||
export * from './subspace.controller';
|
||||
|
91
src/space/controllers/subspace.controller.ts
Normal file
91
src/space/controllers/subspace.controller.ts
Normal file
@ -0,0 +1,91 @@
|
||||
import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { SubSpaceService } from '../services';
|
||||
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { AddSubspaceDto, GetSpaceParam, GetSubSpaceParam } from '../dtos';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { JwtAuthGuard } from '@app/common/guards/jwt.auth.guard';
|
||||
import { PaginationRequestGetListDto } from '@app/common/dto/pagination.request.dto';
|
||||
|
||||
@ApiTags('Space Module')
|
||||
@Controller({
|
||||
version: '1',
|
||||
path: ControllerRoute.SUBSPACE.ROUTE,
|
||||
})
|
||||
export class SubSpaceController {
|
||||
constructor(private readonly subSpaceService: SubSpaceService) {}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post()
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.SUBSPACE.ACTIONS.CREATE_SUBSPACE_SUMMARY,
|
||||
description: ControllerRoute.SUBSPACE.ACTIONS.CREATE_SUBSPACE_DESCRIPTION,
|
||||
})
|
||||
async createSubspace(
|
||||
@Param() params: GetSpaceParam,
|
||||
@Body() addSubspaceDto: AddSubspaceDto,
|
||||
): Promise<BaseResponseDto> {
|
||||
return this.subSpaceService.createSubspace(addSubspaceDto, params);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.SUBSPACE.ACTIONS.LIST_SUBSPACES_SUMMARY,
|
||||
description: ControllerRoute.SUBSPACE.ACTIONS.LIST_SUBSPACES_DESCRIPTION,
|
||||
})
|
||||
@Get()
|
||||
async list(
|
||||
@Param() params: GetSpaceParam,
|
||||
@Query() query: PaginationRequestGetListDto,
|
||||
): Promise<BaseResponseDto> {
|
||||
return this.subSpaceService.list(params, query);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.SUBSPACE.ACTIONS.GET_SUBSPACE_SUMMARY,
|
||||
description: ControllerRoute.SUBSPACE.ACTIONS.GET_SUBSPACE_DESCRIPTION,
|
||||
})
|
||||
@Get(':subSpaceUuid')
|
||||
async findOne(@Param() params: GetSubSpaceParam): Promise<BaseResponseDto> {
|
||||
return this.subSpaceService.findOne(params);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.SUBSPACE.ACTIONS.UPDATE_SUBSPACE_SUMMARY,
|
||||
description: ControllerRoute.SUBSPACE.ACTIONS.UPDATE_SUBSPACE_DESCRIPTION,
|
||||
})
|
||||
@Put(':subSpaceUuid')
|
||||
async updateSubspace(
|
||||
@Param() params: GetSubSpaceParam,
|
||||
@Body() updateSubSpaceDto: AddSubspaceDto,
|
||||
): Promise<BaseResponseDto> {
|
||||
return this.subSpaceService.updateSubSpace(params, updateSubSpaceDto);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@ApiOperation({
|
||||
summary: ControllerRoute.SUBSPACE.ACTIONS.DELETE_SUBSPACE_SUMMARY,
|
||||
description: ControllerRoute.SUBSPACE.ACTIONS.DELETE_SUBSPACE_DESCRIPTION,
|
||||
})
|
||||
@Delete(':subSpaceUuid')
|
||||
async delete(@Param() params: GetSubSpaceParam): Promise<BaseResponseDto> {
|
||||
return this.subSpaceService.delete(params);
|
||||
}
|
||||
}
|
@ -2,3 +2,4 @@ export * from './add.space.dto';
|
||||
export * from './community-space.param';
|
||||
export * from './get.space.param';
|
||||
export * from './user-space.param';
|
||||
export * from './subspace';
|
||||
|
12
src/space/dtos/subspace/add.subspace.dto.ts
Normal file
12
src/space/dtos/subspace/add.subspace.dto.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export class AddSubspaceDto {
|
||||
@ApiProperty({
|
||||
example: 'Meeting Room 1',
|
||||
description: 'Name of the subspace',
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
subspaceName: string;
|
||||
}
|
12
src/space/dtos/subspace/get.subspace.param.ts
Normal file
12
src/space/dtos/subspace/get.subspace.param.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsUUID } from 'class-validator';
|
||||
import { GetSpaceParam } from '../get.space.param';
|
||||
|
||||
export class GetSubSpaceParam extends GetSpaceParam {
|
||||
@ApiProperty({
|
||||
description: 'UUID of the sub space',
|
||||
example: 'd290f1ee-6c54-4b01-90e6-d701748f0851',
|
||||
})
|
||||
@IsUUID()
|
||||
subSpaceUuid: string;
|
||||
}
|
2
src/space/dtos/subspace/index.ts
Normal file
2
src/space/dtos/subspace/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './add.subspace.dto';
|
||||
export * from './get.subspace.param';
|
@ -1,2 +1,3 @@
|
||||
export * from './space.service';
|
||||
export * from './space-user.service';
|
||||
export * from './subspace.service';
|
||||
|
203
src/space/services/subspace.service.ts
Normal file
203
src/space/services/subspace.service.ts
Normal file
@ -0,0 +1,203 @@
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||
import {
|
||||
SpaceRepository,
|
||||
SubspaceRepository,
|
||||
} from '@app/common/modules/space/repositories';
|
||||
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { AddSubspaceDto, GetSpaceParam, GetSubSpaceParam } from '../dtos';
|
||||
import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
|
||||
import {
|
||||
TypeORMCustomModel,
|
||||
TypeORMCustomModelFindAllQuery,
|
||||
} from '@app/common/models/typeOrmCustom.model';
|
||||
import { PageResponse } from '@app/common/dto/pagination.response.dto';
|
||||
import { SubspaceDto } from '@app/common/modules/space/dtos';
|
||||
|
||||
@Injectable()
|
||||
export class SubSpaceService {
|
||||
constructor(
|
||||
private readonly spaceRepository: SpaceRepository,
|
||||
private readonly communityRepository: CommunityRepository,
|
||||
private readonly subspaceRepository: SubspaceRepository,
|
||||
) {}
|
||||
|
||||
async createSubspace(
|
||||
addSubspaceDto: AddSubspaceDto,
|
||||
params: GetSpaceParam,
|
||||
): Promise<BaseResponseDto> {
|
||||
const { communityUuid, spaceUuid } = params;
|
||||
const space = await this.validateCommunityAndSpace(
|
||||
communityUuid,
|
||||
spaceUuid,
|
||||
);
|
||||
|
||||
try {
|
||||
const newSubspace = this.subspaceRepository.create({
|
||||
...addSubspaceDto,
|
||||
space,
|
||||
});
|
||||
|
||||
await this.subspaceRepository.save(newSubspace);
|
||||
|
||||
return new SuccessResponseDto({
|
||||
statusCode: HttpStatus.CREATED,
|
||||
data: newSubspace,
|
||||
message: 'Subspace created successfully',
|
||||
});
|
||||
} catch (error) {
|
||||
throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
async list(
|
||||
params: GetSpaceParam,
|
||||
pageable: Partial<TypeORMCustomModelFindAllQuery>,
|
||||
): Promise<BaseResponseDto> {
|
||||
const { communityUuid, spaceUuid } = params;
|
||||
await this.validateCommunityAndSpace(communityUuid, spaceUuid);
|
||||
|
||||
try {
|
||||
pageable.modelName = 'subspace';
|
||||
pageable.where = { space: { uuid: spaceUuid } };
|
||||
const customModel = TypeORMCustomModel(this.subspaceRepository);
|
||||
|
||||
const { baseResponseDto, paginationResponseDto } =
|
||||
await customModel.findAll(pageable);
|
||||
return new PageResponse<SubspaceDto>(
|
||||
baseResponseDto,
|
||||
paginationResponseDto,
|
||||
);
|
||||
} catch (error) {
|
||||
throw new HttpException(error.message, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
async findOne(params: GetSubSpaceParam): Promise<BaseResponseDto> {
|
||||
const { communityUuid, subSpaceUuid, spaceUuid } = params;
|
||||
await this.validateCommunityAndSpace(communityUuid, spaceUuid);
|
||||
try {
|
||||
const subSpace = await this.subspaceRepository.findOne({
|
||||
where: {
|
||||
uuid: subSpaceUuid,
|
||||
},
|
||||
});
|
||||
|
||||
// If space is not found, throw a NotFoundException
|
||||
if (!subSpace) {
|
||||
throw new HttpException(
|
||||
`Sub Space with UUID ${subSpaceUuid} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
return new SuccessResponseDto({
|
||||
message: `Subspace with ID ${subSpaceUuid} successfully fetched`,
|
||||
data: subSpace,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof HttpException) {
|
||||
throw error; // If it's an HttpException, rethrow it
|
||||
} else {
|
||||
throw new HttpException(
|
||||
'An error occurred while deleting the subspace',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async updateSubSpace(
|
||||
params: GetSubSpaceParam,
|
||||
updateSubSpaceDto: AddSubspaceDto,
|
||||
): Promise<BaseResponseDto> {
|
||||
const { spaceUuid, communityUuid, subSpaceUuid } = params;
|
||||
await this.validateCommunityAndSpace(communityUuid, spaceUuid);
|
||||
|
||||
const subSpace = await this.subspaceRepository.findOne({
|
||||
where: { uuid: subSpaceUuid },
|
||||
});
|
||||
|
||||
if (!subSpace) {
|
||||
throw new HttpException(
|
||||
`SubSpace with ID ${subSpaceUuid} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
Object.assign(subSpace, updateSubSpaceDto);
|
||||
|
||||
await this.subspaceRepository.save(subSpace);
|
||||
|
||||
return new SuccessResponseDto({
|
||||
message: `Subspace with ID ${subSpaceUuid} successfully updated`,
|
||||
data: subSpace,
|
||||
statusCode: HttpStatus.OK,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof HttpException) {
|
||||
throw error;
|
||||
}
|
||||
throw new HttpException(
|
||||
'An error occurred while updating the subspace',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(params: GetSubSpaceParam): Promise<BaseResponseDto> {
|
||||
const { spaceUuid, communityUuid, subSpaceUuid } = params;
|
||||
await this.validateCommunityAndSpace(communityUuid, spaceUuid);
|
||||
|
||||
const subspace = await this.subspaceRepository.findOne({
|
||||
where: { uuid: subSpaceUuid },
|
||||
});
|
||||
|
||||
if (!subspace) {
|
||||
throw new HttpException(
|
||||
`Subspace with ID ${subSpaceUuid} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
await this.subspaceRepository.remove(subspace);
|
||||
|
||||
return new SuccessResponseDto({
|
||||
message: `Subspace with ID ${subSpaceUuid} successfully deleted`,
|
||||
statusCode: HttpStatus.OK,
|
||||
});
|
||||
} catch (error) {
|
||||
throw new HttpException(
|
||||
'An error occurred while deleting the subspace',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async validateCommunityAndSpace(
|
||||
communityUuid: string,
|
||||
spaceUuid: string,
|
||||
) {
|
||||
const community = await this.communityRepository.findOne({
|
||||
where: { uuid: communityUuid },
|
||||
});
|
||||
if (!community) {
|
||||
throw new HttpException(
|
||||
`Community with ID ${communityUuid} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const space = await this.spaceRepository.findOne({
|
||||
where: { uuid: spaceUuid, community: { uuid: communityUuid } },
|
||||
});
|
||||
if (!space) {
|
||||
throw new HttpException(
|
||||
`Space with ID ${spaceUuid} not found`,
|
||||
HttpStatus.NOT_FOUND,
|
||||
);
|
||||
}
|
||||
return space;
|
||||
}
|
||||
}
|
@ -1,11 +1,17 @@
|
||||
import { SpaceRepositoryModule } from '@app/common/modules/space/space.repository.module';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { SpaceController } from './controllers';
|
||||
import { SpaceService, SpaceUserService } from './services';
|
||||
import { SpaceRepository } from '@app/common/modules/space/repositories';
|
||||
import {
|
||||
SpaceController,
|
||||
SpaceUserController,
|
||||
SubSpaceController,
|
||||
} from './controllers';
|
||||
import { SpaceService, SpaceUserService, SubSpaceService } from './services';
|
||||
import {
|
||||
SpaceRepository,
|
||||
SubspaceRepository,
|
||||
} from '@app/common/modules/space/repositories';
|
||||
import { CommunityRepository } from '@app/common/modules/community/repositories';
|
||||
import { SpaceUserController } from './controllers/space-user.controller';
|
||||
import {
|
||||
UserRepository,
|
||||
UserSpaceRepository,
|
||||
@ -13,11 +19,13 @@ import {
|
||||
|
||||
@Module({
|
||||
imports: [ConfigModule, SpaceRepositoryModule],
|
||||
controllers: [SpaceController, SpaceUserController],
|
||||
controllers: [SpaceController, SpaceUserController, SubSpaceController],
|
||||
providers: [
|
||||
SpaceService,
|
||||
SubSpaceService,
|
||||
SpaceRepository,
|
||||
CommunityRepository,
|
||||
SubspaceRepository,
|
||||
UserSpaceRepository,
|
||||
UserRepository,
|
||||
SpaceUserService,
|
||||
|
Reference in New Issue
Block a user