Merge pull request #177 from SyncrowIOT/feat/list-space-model

Feat/list-space-model
This commit is contained in:
hannathkadher
2024-12-19 12:05:27 +04:00
committed by GitHub
7 changed files with 111 additions and 11 deletions
@@ -273,6 +273,10 @@ export class ControllerRoute {
'Create a New Space Model'; 'Create a New Space Model';
public static readonly CREATE_SPACE_MODEL_DESCRIPTION = public static readonly CREATE_SPACE_MODEL_DESCRIPTION =
'This endpoint allows you to create a new space model within a specified project. A space model defines the structure of spaces, including subspaces, products, and product items, and is uniquely identifiable within the project.'; 'This endpoint allows you to create a new space model within a specified project. A space model defines the structure of spaces, including subspaces, products, and product items, and is uniquely identifiable within the project.';
public static readonly LIST_SPACE_MODEL_SUMMARY = 'List Space Models';
public static readonly LIST_SPACE_MODEL_DESCRIPTION =
'This endpoint allows you to retrieve a list of space models within a specified project. Each space model includes its structure, associated subspaces, products, and product items.';
}; };
}; };
@@ -13,6 +13,7 @@ export const PermissionMapping = {
'UPDATE', 'UPDATE',
'DELETE', 'DELETE',
'MODULE_ADD', 'MODULE_ADD',
'MODEL_VIEW',
'ASSIGN_USER_TO_SPACE', 'ASSIGN_USER_TO_SPACE',
'DELETE_USER_FROM_SPACE', 'DELETE_USER_FROM_SPACE',
], ],
@@ -17,6 +17,7 @@ export const RolePermissions = {
'SPACE_UPDATE', 'SPACE_UPDATE',
'SPACE_DELETE', 'SPACE_DELETE',
'SPACE_MODULE_ADD', 'SPACE_MODULE_ADD',
'SPACE_MODEL_VIEW',
'ASSIGN_USER_TO_SPACE', 'ASSIGN_USER_TO_SPACE',
'DELETE_USER_FROM_SPACE', 'DELETE_USER_FROM_SPACE',
'SUBSPACE_VIEW', 'SUBSPACE_VIEW',
@@ -60,6 +61,7 @@ export const RolePermissions = {
'SPACE_UPDATE', 'SPACE_UPDATE',
'SPACE_DELETE', 'SPACE_DELETE',
'SPACE_MODULE_ADD', 'SPACE_MODULE_ADD',
'SPACE_MODEL_VIEW',
'ASSIGN_USER_TO_SPACE', 'ASSIGN_USER_TO_SPACE',
'DELETE_USER_FROM_SPACE', 'DELETE_USER_FROM_SPACE',
'SUBSPACE_VIEW', 'SUBSPACE_VIEW',
@@ -31,7 +31,7 @@ interface FindAllQueryWithDefaults extends CustomFindAllQuery {
function getDefaultQueryOptions( function getDefaultQueryOptions(
query: Partial<TypeORMCustomModelFindAllQuery>, query: Partial<TypeORMCustomModelFindAllQuery>,
): FindManyOptions & FindAllQueryWithDefaults { ): FindManyOptions & FindAllQueryWithDefaults {
const { page, size, includeDisable, modelName, ...rest } = query; const { page, size, includeDisable, include, modelName, ...rest } = query;
// Set default if undefined or null // Set default if undefined or null
const returnPage = page ? Number(page) : 1; const returnPage = page ? Number(page) : 1;
@@ -48,7 +48,9 @@ function getDefaultQueryOptions(
}, },
page: returnPage, page: returnPage,
size: returnSize, size: returnSize,
include: include || undefined,
includeDisable: returnIncludeDisable, includeDisable: returnIncludeDisable,
modelName: modelName || query.modelName, // Ensure modelName is passed through modelName: modelName || query.modelName, // Ensure modelName is passed through
}; };
} }
@@ -97,7 +99,6 @@ export function TypeORMCustomModel(repository: Repository<any>) {
// Use the where clause directly, without wrapping it under 'where' // Use the where clause directly, without wrapping it under 'where'
const whereClause = buildTypeORMWhereClause({ where }); const whereClause = buildTypeORMWhereClause({ where });
console.log('Final where clause:', whereClause);
// Ensure the whereClause is passed directly to findAndCount // Ensure the whereClause is passed directly to findAndCount
const [data, count] = await repository.findAndCount({ const [data, count] = await repository.findAndCount({
@@ -19,6 +19,19 @@ const mappingInclude: { [key: string]: any } = {
project: { project: {
project: true, project: true,
}, },
'space-model': {
subspaceModels: 'subspace-model',
spaceProductModels: 'space-product-model',
},
'subspace-model': {
productModels: 'subspace-product-model',
},
'subspace-product-model': {
itemModels: true,
},
'space-product-model': {
items: true,
},
}; };
export function buildTypeORMIncludeQuery( export function buildTypeORMIncludeQuery(
@@ -30,17 +43,33 @@ export function buildTypeORMIncludeQuery(
const fieldsToInclude: string[] = includeParam.split(','); const fieldsToInclude: string[] = includeParam.split(',');
fieldsToInclude.forEach((field: string) => { fieldsToInclude.forEach((field: string) => {
if (mappingInclude[field]) { const nestedFields = field.split('.');
relations.push(field); // Push mapped field let currentModelName = modelName;
} else { let isValid = true;
console.warn(
`Field ${field} not found in mappingInclude for ${modelName}`, nestedFields.forEach((nestedField, index) => {
); const currentMapping = mappingInclude[currentModelName];
if (currentMapping?.[nestedField]) {
currentModelName =
typeof currentMapping[nestedField] === 'string'
? currentMapping[nestedField]
: currentModelName;
} else {
console.warn(
`Field "${nestedFields.slice(0, index + 1).join('.')}" not found in mappingInclude for model "${currentModelName}"`,
);
isValid = false;
return;
}
});
if (isValid) {
relations.push(field);
} }
}); });
return relations; return relations.length ? relations : undefined;
} }
return undefined; // If no includes, return undefined return undefined;
} }
@@ -1,5 +1,13 @@
import { ControllerRoute } from '@app/common/constants/controller-route'; import { ControllerRoute } from '@app/common/constants/controller-route';
import { Body, Controller, Param, Post, UseGuards } from '@nestjs/common'; import {
Body,
Controller,
Get,
Param,
Post,
Query,
UseGuards,
} from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger'; import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { SpaceModelService } from '../services'; import { SpaceModelService } from '../services';
import { CreateSpaceModelDto } from '../dtos'; import { CreateSpaceModelDto } from '../dtos';
@@ -7,6 +15,7 @@ import { ProjectParam } from 'src/community/dtos';
import { BaseResponseDto } from '@app/common/dto/base.response.dto'; import { BaseResponseDto } from '@app/common/dto/base.response.dto';
import { PermissionsGuard } from 'src/guards/permissions.guard'; import { PermissionsGuard } from 'src/guards/permissions.guard';
import { Permissions } from 'src/decorators/permissions.decorator'; import { Permissions } from 'src/decorators/permissions.decorator';
import { PaginationRequestGetListDto } from '@app/common/dto/pagination.request.dto';
@ApiTags('Space Model Module') @ApiTags('Space Model Module')
@Controller({ @Controller({
@@ -34,4 +43,20 @@ export class SpaceModelController {
projectParam, projectParam,
); );
} }
@ApiBearerAuth()
@UseGuards(PermissionsGuard)
@Permissions('SPACE_MODEL_VIEW')
@ApiOperation({
summary: ControllerRoute.SPACE_MODEL.ACTIONS.LIST_SPACE_MODEL_SUMMARY,
description:
ControllerRoute.SPACE_MODEL.ACTIONS.LIST_SPACE_MODEL_DESCRIPTION,
})
@Get()
async listSpaceModel(
@Param() projectParam: ProjectParam,
@Query() query: PaginationRequestGetListDto,
): Promise<BaseResponseDto> {
return await this.spaceModelService.list(projectParam, query);
}
} }
@@ -7,6 +7,12 @@ import { SuccessResponseDto } from '@app/common/dto/success.response.dto';
import { SubSpaceModelService } from './subspace/subspace-model.service'; import { SubSpaceModelService } from './subspace/subspace-model.service';
import { SpaceProductModelService } from './space-product-model.service'; import { SpaceProductModelService } from './space-product-model.service';
import { DataSource } from 'typeorm'; import { DataSource } from 'typeorm';
import {
TypeORMCustomModel,
TypeORMCustomModelFindAllQuery,
} from '@app/common/models/typeOrmCustom.model';
import { PageResponse } from '@app/common/dto/pagination.response.dto';
import { SpaceModelDto } from '@app/common/modules/space-model/dtos';
@Injectable() @Injectable()
export class SpaceModelService { export class SpaceModelService {
@@ -87,6 +93,38 @@ export class SpaceModelService {
} }
} }
async list(
param: ProjectParam,
pageable: Partial<TypeORMCustomModelFindAllQuery>,
) {
await this.validateProject(param.projectUuid);
try {
pageable.modelName = 'space-model';
pageable.where = {
project: { uuid: param.projectUuid },
};
pageable.include =
'subspaceModels,spaceProductModels,subspaceModels.productModels,subspaceModels.productModels.itemModels,spaceProductModels.items';
const customModel = TypeORMCustomModel(this.spaceModelRepository);
const { baseResponseDto, paginationResponseDto } =
await customModel.findAll(pageable);
return new PageResponse<SpaceModelDto>(
baseResponseDto,
paginationResponseDto,
);
} catch (error) {
throw new HttpException(
error.message ||
'An error occurred while fetching space models in project.',
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
async validateProject(projectUuid: string) { async validateProject(projectUuid: string) {
const project = await this.projectRepository.findOne({ const project = await this.projectRepository.findOne({
where: { where: {