-
-
Notifications
You must be signed in to change notification settings - Fork 306
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: optimize ui display * feat: change password to trigger browser autosave * feat: pin space and base * chore: remove console code
- Loading branch information
Showing
47 changed files
with
1,014 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
apps/nestjs-backend/src/event-emitter/listeners/pin.listener.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Injectable, Logger } from '@nestjs/common'; | ||
import { OnEvent } from '@nestjs/event-emitter'; | ||
import { PrismaService } from '@teable/db-main-prisma'; | ||
import type { SpaceDeleteEvent, BaseDeleteEvent } from '../events'; | ||
import { Events } from '../events'; | ||
|
||
@Injectable() | ||
export class PinListener { | ||
private readonly logger = new Logger(PinListener.name); | ||
|
||
constructor(private readonly prismaService: PrismaService) {} | ||
|
||
@OnEvent(Events.BASE_DELETE, { async: true }) | ||
@OnEvent(Events.SPACE_DELETE, { async: true }) | ||
async spaceAndBaseDelete(listenerEvent: SpaceDeleteEvent | BaseDeleteEvent) { | ||
let id: string = ''; | ||
if (listenerEvent.name === Events.SPACE_DELETE) { | ||
id = listenerEvent.payload.spaceId; | ||
} | ||
if (listenerEvent.name === Events.BASE_DELETE) { | ||
id = listenerEvent.payload.baseId; | ||
} | ||
|
||
if (!id) { | ||
return; | ||
} | ||
|
||
await this.prismaService.pinResource.deleteMany({ | ||
where: { | ||
resourceId: id, | ||
}, | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { Body, Controller, Delete, Get, Post, Put, Query } from '@nestjs/common'; | ||
import type { GetPinListVo } from '@teable/openapi'; | ||
import { | ||
AddPinRo, | ||
DeletePinRo, | ||
addPinRoSchema, | ||
deletePinRoSchema, | ||
UpdatePinOrderRo, | ||
updatePinOrderRoSchema, | ||
} from '@teable/openapi'; | ||
import { ZodValidationPipe } from '../../zod.validation.pipe'; | ||
import { PinService } from './pin.service'; | ||
|
||
@Controller('api/pin') | ||
export class PinController { | ||
constructor(private readonly pinService: PinService) {} | ||
|
||
@Post() | ||
async add(@Body(new ZodValidationPipe(addPinRoSchema)) query: AddPinRo) { | ||
return this.pinService.addPin(query); | ||
} | ||
|
||
@Delete() | ||
async delete(@Query(new ZodValidationPipe(deletePinRoSchema)) query: DeletePinRo) { | ||
return this.pinService.deletePin(query); | ||
} | ||
|
||
@Get('list') | ||
async getList(): Promise<GetPinListVo> { | ||
return this.pinService.getList(); | ||
} | ||
|
||
@Put('order') | ||
async updateOrder(@Body(new ZodValidationPipe(updatePinOrderRoSchema)) body: UpdatePinOrderRo) { | ||
return this.pinService.updateOrder(body); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { PinController } from './pin.controller'; | ||
import { PinService } from './pin.service'; | ||
|
||
@Module({ | ||
providers: [PinService], | ||
controllers: [PinController], | ||
}) | ||
export class PinModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; | ||
import type { Prisma } from '@teable/db-main-prisma'; | ||
import { PrismaService } from '@teable/db-main-prisma'; | ||
import type { | ||
PinType, | ||
GetPinListVo, | ||
AddPinRo, | ||
DeletePinRo, | ||
UpdatePinOrderRo, | ||
} from '@teable/openapi'; | ||
import { ClsService } from 'nestjs-cls'; | ||
import type { IClsStore } from '../../types/cls'; | ||
import { updateOrder } from '../../utils/update-order'; | ||
|
||
@Injectable() | ||
export class PinService { | ||
constructor( | ||
private readonly prismaService: PrismaService, | ||
private readonly cls: ClsService<IClsStore> | ||
) {} | ||
|
||
private async getMaxOrder(where: Prisma.PinResourceWhereInput) { | ||
const aggregate = await this.prismaService.pinResource.aggregate({ | ||
where, | ||
_max: { order: true }, | ||
}); | ||
return aggregate._max.order || 0; | ||
} | ||
|
||
async addPin(query: AddPinRo) { | ||
const { type, id } = query; | ||
const maxOrder = await this.getMaxOrder({ | ||
createdBy: this.cls.get('user.id'), | ||
}); | ||
return this.prismaService.pinResource | ||
.create({ | ||
data: { | ||
type, | ||
resourceId: id, | ||
createdBy: this.cls.get('user.id'), | ||
order: maxOrder + 1, | ||
}, | ||
}) | ||
.catch(() => { | ||
throw new BadRequestException('Pin already exists'); | ||
}); | ||
} | ||
|
||
async deletePin(query: DeletePinRo) { | ||
const { id, type } = query; | ||
return this.prismaService.pinResource | ||
.delete({ | ||
where: { | ||
// eslint-disable-next-line @typescript-eslint/naming-convention | ||
createdBy_resourceId: { | ||
resourceId: id, | ||
createdBy: this.cls.get('user.id'), | ||
}, | ||
type, | ||
}, | ||
}) | ||
.catch(() => { | ||
throw new NotFoundException('Pin not found'); | ||
}); | ||
} | ||
|
||
async getList(): Promise<GetPinListVo> { | ||
const list = await this.prismaService.pinResource.findMany({ | ||
where: { | ||
createdBy: this.cls.get('user.id'), | ||
}, | ||
select: { | ||
resourceId: true, | ||
type: true, | ||
order: true, | ||
}, | ||
orderBy: { | ||
order: 'asc', | ||
}, | ||
}); | ||
return list.map((item) => ({ | ||
id: item.resourceId, | ||
type: item.type as PinType, | ||
order: item.order, | ||
})); | ||
} | ||
|
||
async updateOrder(data: UpdatePinOrderRo) { | ||
const { id, type, position, anchorId, anchorType } = data; | ||
|
||
const item = await this.prismaService.pinResource | ||
.findFirstOrThrow({ | ||
select: { order: true, id: true }, | ||
where: { | ||
resourceId: id, | ||
type, | ||
createdBy: this.cls.get('user.id'), | ||
}, | ||
}) | ||
.catch(() => { | ||
throw new NotFoundException('Pin not found'); | ||
}); | ||
|
||
const anchorItem = await this.prismaService.pinResource | ||
.findFirstOrThrow({ | ||
select: { order: true, id: true }, | ||
where: { | ||
resourceId: anchorId, | ||
type: anchorType, | ||
createdBy: this.cls.get('user.id'), | ||
}, | ||
}) | ||
.catch(() => { | ||
throw new NotFoundException('Pin Anchor not found'); | ||
}); | ||
|
||
await updateOrder({ | ||
query: undefined, | ||
position, | ||
item, | ||
anchorItem, | ||
getNextItem: async (whereOrder, align) => { | ||
return this.prismaService.pinResource.findFirst({ | ||
select: { order: true, id: true }, | ||
where: { | ||
resourceId: id, | ||
type: type, | ||
order: whereOrder, | ||
}, | ||
orderBy: { order: align }, | ||
}); | ||
}, | ||
update: async (_, id, data) => { | ||
await this.prismaService.pinResource.update({ | ||
data: { order: data.newOrder }, | ||
where: { id }, | ||
}); | ||
}, | ||
shuffle: async () => { | ||
const orderKey = position === 'before' ? 'lt' : 'gt'; | ||
const dataOrderKey = position === 'before' ? 'decrement' : 'increment'; | ||
await this.prismaService.pinResource.updateMany({ | ||
data: { order: { [dataOrderKey]: 1 } }, | ||
where: { | ||
createdBy: this.cls.get('user.id'), | ||
order: { | ||
[orderKey]: anchorItem.order, | ||
}, | ||
}, | ||
}); | ||
}, | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.