Skip to content

Commit

Permalink
refactor: view+table+base updateOrder
Browse files Browse the repository at this point in the history
  • Loading branch information
tea-artist committed Mar 18, 2024
1 parent e9075ab commit 0752cf3
Show file tree
Hide file tree
Showing 30 changed files with 593 additions and 174 deletions.
15 changes: 13 additions & 2 deletions apps/nestjs-backend/src/features/base/base.controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable sonarjs/no-duplicate-string */
import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common';
import { Body, Controller, Delete, Get, Param, Patch, Post, Put } from '@nestjs/common';
import {
createBaseRoSchema,
duplicateBaseRoSchema,
Expand All @@ -9,6 +9,8 @@ import {
IDuplicateBaseRo,
createBaseFromTemplateRoSchema,
ICreateBaseFromTemplateRo,
updateOrderRoSchema,
IUpdateOrderRo,
} from '@teable/openapi';
import type {
ICreateBaseVo,
Expand Down Expand Up @@ -78,6 +80,15 @@ export class BaseController {
return await this.baseService.updateBase(baseId, updateBaseRo);
}

@Put(':baseId/order')
@Permissions('base|update')
async updateOrder(
@Param('baseId') baseId: string,
@Body(new ZodValidationPipe(updateOrderRoSchema)) updateOrderRo: IUpdateOrderRo
) {
return await this.baseService.updateOrder(baseId, updateOrderRo);
}

@Permissions('base|read')
@Get(':baseId')
async getBaseById(@Param('baseId') baseId: string): Promise<IGetBaseVo> {
Expand All @@ -86,7 +97,7 @@ export class BaseController {

@Get('access/all')
async getAllBase(): Promise<IGetBaseVo[]> {
return await this.baseService.getBaseList();
return await this.baseService.getAllBaseList();
}

@Delete(':baseId')
Expand Down
85 changes: 75 additions & 10 deletions apps/nestjs-backend/src/features/base/base.service.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { Injectable, Logger, NotFoundException } from '@nestjs/common';
import { generateBaseId } from '@teable/core';
import { PrismaService } from '@teable/db-main-prisma';
import type {
ICreateBaseFromTemplateRo,
ICreateBaseRo,
IDuplicateBaseRo,
IUpdateBaseRo,
IUpdateOrderRo,
} from '@teable/openapi';
import { ClsService } from 'nestjs-cls';
import { IThresholdConfig, ThresholdConfig } from '../../configs/threshold.config';
import { InjectDbProvider } from '../../db-provider/db.provider';
import { IDbProvider } from '../../db-provider/db.provider.interface';
import type { IClsStore } from '../../types/cls';
import { updateOrder } from '../../utils/update-order';
import { PermissionService } from '../auth/permission.service';
import { CollaboratorService } from '../collaborator/collaborator.service';
import { BaseDuplicateService } from './base-duplicate.service';

@Injectable()
export class BaseService {
private logger = new Logger(BaseService.name);

constructor(
private readonly prismaService: PrismaService,
private readonly cls: ClsService<IClsStore>,
Expand All @@ -37,7 +41,6 @@ export class BaseService {
select: {
id: true,
name: true,
order: true,
icon: true,
spaceId: true,
},
Expand All @@ -58,7 +61,7 @@ export class BaseService {
};
}

async getBaseList() {
async getAllBaseList() {
const userId = this.cls.get('user.id');
const { spaceIds, baseIds, roleMap } =
await this.collaboratorService.getCollaboratorsBaseAndSpaceArray(userId);
Expand All @@ -85,9 +88,7 @@ export class BaseService {
},
],
},
orderBy: {
createdTime: 'asc',
},
orderBy: [{ spaceId: 'asc' }, { order: 'asc' }],
});
return baseList.map((base) => ({ ...base, role: roleMap[base.id] || roleMap[base.spaceId] }));
}
Expand All @@ -105,8 +106,7 @@ export class BaseService {
const { name, spaceId } = createBaseRo;

return this.prismaService.$transaction(async (prisma) => {
const order =
createBaseRo.order == null ? (await this.getMaxOrder(spaceId)) + 1 : createBaseRo.order;
const order = (await this.getMaxOrder(spaceId)) + 1;

const base = await prisma.base.create({
data: {
Expand All @@ -121,7 +121,6 @@ export class BaseService {
name: true,
icon: true,
spaceId: true,
order: true,
},
});

Expand All @@ -148,7 +147,6 @@ export class BaseService {
id: true,
name: true,
spaceId: true,
order: true,
},
where: {
id: baseId,
Expand All @@ -157,6 +155,73 @@ export class BaseService {
});
}

async shuffle(spaceId: string) {
const bases = await this.prismaService.base.findMany({
where: { spaceId, deletedTime: null },
select: { id: true },
orderBy: { order: 'asc' },
});

this.logger.log(`lucky base shuffle! ${spaceId}`, 'shuffle');

await this.prismaService.$tx(async (prisma) => {
for (let i = 0; i < bases.length; i++) {
const base = bases[i];
await prisma.base.update({
data: { order: i },
where: { id: base.id },
});
}
});
}

async updateOrder(baseId: string, orderRo: IUpdateOrderRo) {
const { anchorId, position } = orderRo;

const base = await this.prismaService.base
.findFirstOrThrow({
select: { spaceId: true, order: true, id: true },
where: { id: baseId, deletedTime: null },
})
.catch(() => {
throw new NotFoundException(`Base ${baseId} not found`);
});

const anchorBase = await this.prismaService.base
.findFirstOrThrow({
select: { order: true, id: true },
where: { spaceId: base.spaceId, id: anchorId, deletedTime: null },
})
.catch(() => {
throw new NotFoundException(`Anchor ${anchorId} not found`);
});

await updateOrder({
parentId: base.spaceId,
position,
item: base,
anchorItem: anchorBase,
getNextItem: async (whereOrder, align) => {
return this.prismaService.base.findFirst({
select: { order: true, id: true },
where: {
spaceId: base.spaceId,
deletedTime: null,
order: whereOrder,
},
orderBy: { order: align },
});
},
updateSingle: async (_, id, data) => {
await this.prismaService.base.update({
data: { order: data.newOrder },
where: { id },
});
},
shuffle: this.shuffle.bind(this),
});
}

async deleteBase(baseId: string) {
const userId = this.cls.get('user.id');

Expand Down
3 changes: 2 additions & 1 deletion apps/nestjs-backend/src/features/space/space.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,10 @@ export class SpaceService {
deletedTime: null,
},
orderBy: {
createdTime: 'asc',
order: 'asc',
},
});

return baseList.map((base) => ({ ...base, role: roleMap[base.id] || roleMap[base.spaceId] }));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ import {
ITableDescriptionRo,
ITableIconRo,
ITableNameRo,
ITableOrderRo,
IUpdateOrderRo,
sqlQuerySchema,
tableDescriptionRoSchema,
tableIconRoSchema,
tableNameRoSchema,
tableOrderRoSchema,
updateOrderRoSchema,
} from '@teable/openapi';
import { ZodValidationPipe } from '../../../zod.validation.pipe';
import { Permissions } from '../../auth/decorators/permissions.decorator';
Expand Down Expand Up @@ -111,9 +111,9 @@ export class TableController {
async updateOrder(
@Param('baseId') baseId: string,
@Param('tableId') tableId: string,
@Body(new ZodValidationPipe(tableOrderRoSchema)) tableOrderRo: ITableOrderRo
@Body(new ZodValidationPipe(updateOrderRoSchema)) updateOrderRo: IUpdateOrderRo
) {
return await this.tableOpenApiService.updateOrder(baseId, tableId, tableOrderRo.order);
return await this.tableOpenApiService.updateOrder(baseId, tableId, updateOrderRo);
}

@Post()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import type {
} from '@teable/core';
import { FieldKeyType, FieldType } from '@teable/core';
import { PrismaService } from '@teable/db-main-prisma';
import type { IUpdateOrderRo } from '@teable/openapi';
import { ThresholdConfig, IThresholdConfig } from '../../../configs/threshold.config';
import { InjectDbProvider } from '../../../db-provider/db.provider';
import { IDbProvider } from '../../../db-provider/db.provider.interface';
import { updateOrder } from '../../../utils/update-order';
import { LinkService } from '../../calculation/link.service';
import { FieldCreatingService } from '../../field/field-calculate/field-creating.service';
import { FieldSupplementService } from '../../field/field-calculate/field-supplement.service';
Expand Down Expand Up @@ -352,18 +354,70 @@ export class TableOpenApiService {
});
}

async updateOrder(baseId: string, tableId: string, order: number) {
const orderExist = await this.prismaService.tableMeta.findFirst({
where: { baseId, order, deletedTime: null },
async shuffle(baseId: string) {
const tables = await this.prismaService.tableMeta.findMany({
where: { baseId, deletedTime: null },
select: { id: true },
orderBy: { order: 'asc' },
});

if (orderExist) {
throw new BadRequestException('Table order could not be duplicate');
}
this.logger.log(`lucky table shuffle! ${baseId}`, 'shuffle');

await this.prismaService.$tx(async () => {
await this.tableService.updateTable(baseId, tableId, { order });
for (let i = 0; i < tables.length; i++) {
const table = tables[i];
await this.tableService.updateTable(baseId, table.id, { order: i });
}
});
}

async updateOrder(baseId: string, tableId: string, orderRo: IUpdateOrderRo) {
const { anchorId, position } = orderRo;

const table = await this.prismaService.tableMeta
.findFirstOrThrow({
select: { order: true, id: true },
where: { baseId, id: tableId, deletedTime: null },
})
.catch(() => {
throw new NotFoundException(`Table ${tableId} not found`);
});

const anchorTable = await this.prismaService.tableMeta
.findFirstOrThrow({
select: { order: true, id: true },
where: { baseId, id: anchorId, deletedTime: null },
})
.catch(() => {
throw new NotFoundException(`Anchor ${anchorId} not found`);
});

await updateOrder({
parentId: baseId,
position,
item: table,
anchorItem: anchorTable,
getNextItem: async (whereOrder, align) => {
return this.prismaService.tableMeta.findFirst({
select: { order: true, id: true },
where: {
baseId,
deletedTime: null,
order: whereOrder,
},
orderBy: { order: align },
});
},
updateSingle: async (
parentId: string,
id: string,
data: { newOrder: number; oldOrder: number }
) => {
await this.prismaService.$tx(async () => {
await this.tableService.updateTable(parentId, id, { order: data.newOrder });
});
},
shuffle: this.shuffle.bind(this),
});
}
}
1 change: 0 additions & 1 deletion apps/nestjs-backend/src/features/table/table.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,6 @@ export class TableService implements IAdapterService {
...table,
description: table.description ?? undefined,
icon: table.icon ?? undefined,
order: table.order,
lastModifiedTime: tableTime[i] || table.createdTime.toISOString(),
defaultViewId: tableDefaultViewIds[i],
},
Expand Down

0 comments on commit 0752cf3

Please sign in to comment.