mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-07-09 22:57:24 +00:00
add order space API (#459)
This commit is contained in:
@ -220,6 +220,11 @@ export class ControllerRoute {
|
||||
public static readonly UPDATE_SPACE_DESCRIPTION =
|
||||
'Updates a space by its UUID and community ID. You can update the name, parent space, and other properties. If a parent space is provided and not already a parent, its `isParent` flag will be set to true.';
|
||||
|
||||
public static readonly UPDATE_CHILDREN_SPACES_ORDER_OF_A_SPACE_SUMMARY =
|
||||
'Update the order of child spaces under a specific parent space';
|
||||
public static readonly UPDATE_CHILDREN_SPACES_ORDER_OF_A_SPACE_DESCRIPTION =
|
||||
'Updates the order of child spaces under a specific parent space. You can provide a new order for the child spaces.';
|
||||
|
||||
public static readonly GET_HEIRARCHY_SUMMARY = 'Get space hierarchy';
|
||||
public static readonly GET_HEIRARCHY_DESCRIPTION =
|
||||
'This endpoint retrieves the hierarchical structure of spaces under a given space ID. It returns all the child spaces nested within the specified space, organized by their parent-child relationships. ';
|
||||
|
@ -6,9 +6,9 @@ import {
|
||||
OneToMany,
|
||||
OneToOne,
|
||||
} from 'typeorm';
|
||||
import { SpaceDto } from '../dtos';
|
||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||
import { AqiSpaceDailyPollutantStatsEntity } from '../../aqi/entities';
|
||||
import { BookableSpaceEntity } from '../../booking/entities';
|
||||
import { CommunityEntity } from '../../community/entities';
|
||||
import { DeviceEntity } from '../../device/entities';
|
||||
import { InviteUserSpaceEntity } from '../../Invite-user/entities';
|
||||
@ -17,9 +17,9 @@ import { PresenceSensorDailySpaceEntity } from '../../presence-sensor/entities';
|
||||
import { SceneEntity } from '../../scene/entities';
|
||||
import { SpaceModelEntity } from '../../space-model';
|
||||
import { UserSpaceEntity } from '../../user/entities';
|
||||
import { SpaceDto } from '../dtos';
|
||||
import { SpaceProductAllocationEntity } from './space-product-allocation.entity';
|
||||
import { SubspaceEntity } from './subspace/subspace.entity';
|
||||
import { BookableSpaceEntity } from '../../booking/entities';
|
||||
|
||||
@Entity({ name: 'space' })
|
||||
export class SpaceEntity extends AbstractEntity<SpaceDto> {
|
||||
@ -64,6 +64,12 @@ export class SpaceEntity extends AbstractEntity<SpaceDto> {
|
||||
})
|
||||
public disabled: boolean;
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: Number,
|
||||
})
|
||||
public order?: number;
|
||||
|
||||
@OneToMany(() => SubspaceEntity, (subspace) => subspace.space, {
|
||||
nullable: true,
|
||||
})
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { SpaceService } from '../services';
|
||||
import { ControllerRoute } from '@app/common/constants/controller-route';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
@ -12,12 +11,14 @@ import {
|
||||
Query,
|
||||
UseGuards,
|
||||
} from '@nestjs/common';
|
||||
import { AddSpaceDto, CommunitySpaceParam, UpdateSpaceDto } from '../dtos';
|
||||
import { BaseResponseDto } from '@app/common/dto/base.response.dto';
|
||||
import { GetSpaceParam } from '../dtos/get.space.param';
|
||||
import { PermissionsGuard } from 'src/guards/permissions.guard';
|
||||
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
import { Permissions } from 'src/decorators/permissions.decorator';
|
||||
import { PermissionsGuard } from 'src/guards/permissions.guard';
|
||||
import { AddSpaceDto, CommunitySpaceParam, UpdateSpaceDto } from '../dtos';
|
||||
import { GetSpaceDto } from '../dtos/get.space.dto';
|
||||
import { GetSpaceParam } from '../dtos/get.space.param';
|
||||
import { OrderSpacesDto } from '../dtos/order.spaces.dto';
|
||||
import { SpaceService } from '../services';
|
||||
|
||||
@ApiTags('Space Module')
|
||||
@Controller({
|
||||
@ -65,6 +66,26 @@ export class SpaceController {
|
||||
);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(PermissionsGuard)
|
||||
@Permissions('SPACE_UPDATE')
|
||||
@ApiOperation({
|
||||
summary:
|
||||
ControllerRoute.SPACE.ACTIONS
|
||||
.UPDATE_CHILDREN_SPACES_ORDER_OF_A_SPACE_SUMMARY,
|
||||
description:
|
||||
ControllerRoute.SPACE.ACTIONS
|
||||
.UPDATE_CHILDREN_SPACES_ORDER_OF_A_SPACE_DESCRIPTION,
|
||||
})
|
||||
@Post(':parentSpaceUuid/spaces/order')
|
||||
async updateSpacesOrder(
|
||||
@Body() orderSpacesDto: OrderSpacesDto,
|
||||
@Param() communitySpaceParam: CommunitySpaceParam,
|
||||
@Param('parentSpaceUuid') parentSpaceUuid: string,
|
||||
) {
|
||||
return this.spaceService.updateSpacesOrder(parentSpaceUuid, orderSpacesDto);
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(PermissionsGuard)
|
||||
@Permissions('SPACE_DELETE')
|
||||
|
13
src/space/dtos/order.spaces.dto.ts
Normal file
13
src/space/dtos/order.spaces.dto.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { ArrayUnique, IsNotEmpty, IsUUID } from 'class-validator';
|
||||
|
||||
export class OrderSpacesDto {
|
||||
@ApiProperty({
|
||||
description: 'List of children spaces associated with the space',
|
||||
type: [String],
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@ArrayUnique()
|
||||
@IsUUID('4', { each: true, message: 'Invalid space UUID provided' })
|
||||
spacesUuids: string[];
|
||||
}
|
@ -33,6 +33,7 @@ import {
|
||||
} from '../dtos';
|
||||
import { CreateProductAllocationDto } from '../dtos/create-product-allocation.dto';
|
||||
import { GetSpaceDto } from '../dtos/get.space.dto';
|
||||
import { OrderSpacesDto } from '../dtos/order.spaces.dto';
|
||||
import { SpaceWithParentsDto } from '../dtos/space.parents.dto';
|
||||
import { SpaceProductAllocationService } from './space-product-allocation.service';
|
||||
import { ValidationService } from './space-validation.service';
|
||||
@ -355,6 +356,32 @@ export class SpaceService {
|
||||
}
|
||||
}
|
||||
|
||||
async updateSpacesOrder(
|
||||
parentSpaceUuid: string,
|
||||
{ spacesUuids }: OrderSpacesDto,
|
||||
) {
|
||||
try {
|
||||
await this.spaceRepository.update(
|
||||
{ uuid: In(spacesUuids), parent: { uuid: parentSpaceUuid } },
|
||||
{
|
||||
order: () =>
|
||||
'CASE ' +
|
||||
spacesUuids
|
||||
.map((s, index) => `WHEN uuid = '${s}' THEN ${index + 1}`)
|
||||
.join(' ') +
|
||||
' END',
|
||||
},
|
||||
);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error updating spaces order:', error);
|
||||
throw new HttpException(
|
||||
'An error occurred while updating spaces order',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async delete(params: GetSpaceParam): Promise<BaseResponseDto> {
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
@ -709,10 +736,21 @@ export class SpaceService {
|
||||
rootSpaces.push(map.get(space.uuid)!); // Push only root spaces
|
||||
}
|
||||
});
|
||||
|
||||
rootSpaces.forEach(this.sortSpaceChildren.bind(this));
|
||||
return rootSpaces;
|
||||
}
|
||||
|
||||
private sortSpaceChildren(space: SpaceEntity) {
|
||||
if (space.children && space.children.length > 0) {
|
||||
space.children.sort((a, b) => {
|
||||
const aOrder = a.order ?? Infinity;
|
||||
const bOrder = b.order ?? Infinity;
|
||||
return aOrder - bOrder;
|
||||
});
|
||||
space.children.forEach(this.sortSpaceChildren.bind(this)); // Recursively sort children of children
|
||||
}
|
||||
}
|
||||
|
||||
private validateSpaceCreationCriteria({
|
||||
spaceModelUuid,
|
||||
productAllocations,
|
||||
|
Reference in New Issue
Block a user