mirror of
https://github.com/docmost/docmost.git
synced 2025-11-15 03:51:11 +10:00
Add new page module and services; refactor existing entities
- Introduced a new page module with associated services. - Refactored TypeORM entities in user and workspace modules.
This commit is contained in:
@ -2,8 +2,9 @@ import { Module } from '@nestjs/common';
|
|||||||
import { UserModule } from './user/user.module';
|
import { UserModule } from './user/user.module';
|
||||||
import { AuthModule } from './auth/auth.module';
|
import { AuthModule } from './auth/auth.module';
|
||||||
import { WorkspaceModule } from './workspace/workspace.module';
|
import { WorkspaceModule } from './workspace/workspace.module';
|
||||||
|
import { PageModule } from './page/page.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [UserModule, AuthModule, WorkspaceModule],
|
imports: [UserModule, AuthModule, WorkspaceModule, PageModule],
|
||||||
})
|
})
|
||||||
export class CoreModule {}
|
export class CoreModule {}
|
||||||
|
|||||||
18
server/src/core/page/dto/create-page.dto.ts
Normal file
18
server/src/core/page/dto/create-page.dto.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { IsOptional, IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class CreatePageDto {
|
||||||
|
@IsOptional()
|
||||||
|
title?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
content?: string;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
parentId?: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
creatorId: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
workspaceId: string;
|
||||||
|
}
|
||||||
4
server/src/core/page/dto/update-page.dto.ts
Normal file
4
server/src/core/page/dto/update-page.dto.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { PartialType } from '@nestjs/mapped-types';
|
||||||
|
import { CreatePageDto } from './create-page.dto';
|
||||||
|
|
||||||
|
export class UpdatePageDto extends PartialType(CreatePageDto) {}
|
||||||
88
server/src/core/page/entities/page.entity.ts
Normal file
88
server/src/core/page/entities/page.entity.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import {
|
||||||
|
Entity,
|
||||||
|
PrimaryGeneratedColumn,
|
||||||
|
Column,
|
||||||
|
CreateDateColumn,
|
||||||
|
UpdateDateColumn,
|
||||||
|
ManyToOne,
|
||||||
|
JoinColumn,
|
||||||
|
OneToMany,
|
||||||
|
DeleteDateColumn,
|
||||||
|
} from 'typeorm';
|
||||||
|
import { User } from '../../user/entities/user.entity';
|
||||||
|
import { Workspace } from '../../workspace/entities/workspace.entity';
|
||||||
|
|
||||||
|
@Entity('pages')
|
||||||
|
export class Page {
|
||||||
|
@PrimaryGeneratedColumn('uuid')
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@Column({ length: 500, nullable: true })
|
||||||
|
title: string;
|
||||||
|
|
||||||
|
@Column({ type: 'text', nullable: true })
|
||||||
|
content: string;
|
||||||
|
|
||||||
|
@Column({ type: 'text', nullable: true })
|
||||||
|
html: string;
|
||||||
|
|
||||||
|
@Column({ type: 'jsonb', nullable: true })
|
||||||
|
json: any;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
slug: string;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
icon: string;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
coverPhoto: string;
|
||||||
|
|
||||||
|
@Column({ length: 255, nullable: true })
|
||||||
|
editor: string;
|
||||||
|
|
||||||
|
@Column({ length: 255, nullable: true })
|
||||||
|
shareId: string;
|
||||||
|
|
||||||
|
@Column({ type: 'uuid', nullable: true })
|
||||||
|
parentPageId: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
creatorId: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => User)
|
||||||
|
@JoinColumn({ name: 'creatorId' })
|
||||||
|
creator: User;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
workspaceId: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => Workspace, { onDelete: 'CASCADE' })
|
||||||
|
@JoinColumn({ name: 'workspaceId' })
|
||||||
|
workspace: Workspace;
|
||||||
|
|
||||||
|
@Column({ type: 'boolean', default: false })
|
||||||
|
isLocked: boolean;
|
||||||
|
|
||||||
|
@Column({ length: 255, nullable: true })
|
||||||
|
status: string;
|
||||||
|
|
||||||
|
@Column({ type: 'date', nullable: true })
|
||||||
|
publishedAt: string;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
createdAt: Date;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updatedAt: Date;
|
||||||
|
|
||||||
|
@DeleteDateColumn({ nullable: true })
|
||||||
|
deletedAt: Date;
|
||||||
|
|
||||||
|
@ManyToOne(() => Page, (page) => page.childPages)
|
||||||
|
@JoinColumn({ name: 'parentPageId' })
|
||||||
|
parentPage: Page;
|
||||||
|
|
||||||
|
@OneToMany(() => Page, (page) => page.parentPage, { onDelete: 'CASCADE' })
|
||||||
|
childPages: Page[];
|
||||||
|
}
|
||||||
20
server/src/core/page/page.controller.spec.ts
Normal file
20
server/src/core/page/page.controller.spec.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { PageController } from './page.controller';
|
||||||
|
import { PageService } from './page.service';
|
||||||
|
|
||||||
|
describe('PageController', () => {
|
||||||
|
let controller: PageController;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
controllers: [PageController],
|
||||||
|
providers: [PageService],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
controller = module.get<PageController>(PageController);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(controller).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
23
server/src/core/page/page.controller.ts
Normal file
23
server/src/core/page/page.controller.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { Controller, Post, Body, Delete, Get, Param } from "@nestjs/common";
|
||||||
|
import { PageService } from './page.service';
|
||||||
|
import { CreatePageDto } from './dto/create-page.dto';
|
||||||
|
|
||||||
|
@Controller('page')
|
||||||
|
export class PageController {
|
||||||
|
constructor(private readonly pageService: PageService) {}
|
||||||
|
|
||||||
|
@Post('create')
|
||||||
|
async create(@Body() createPageDto: CreatePageDto) {
|
||||||
|
return this.pageService.create(createPageDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('page/:id')
|
||||||
|
async getPage(@Param('id') pageId: string) {
|
||||||
|
return this.pageService.findById(pageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Delete('delete/:id')
|
||||||
|
async delete(@Param('id') pageId: string) {
|
||||||
|
await this.pageService.delete(pageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
13
server/src/core/page/page.module.ts
Normal file
13
server/src/core/page/page.module.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { PageService } from './page.service';
|
||||||
|
import { PageController } from './page.controller';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { Page } from './entities/page.entity';
|
||||||
|
import { PageRepository } from './repositories/page.repository';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [TypeOrmModule.forFeature([Page])],
|
||||||
|
controllers: [PageController],
|
||||||
|
providers: [PageService, PageRepository],
|
||||||
|
})
|
||||||
|
export class PageModule {}
|
||||||
18
server/src/core/page/page.service.spec.ts
Normal file
18
server/src/core/page/page.service.spec.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { PageService } from './page.service';
|
||||||
|
|
||||||
|
describe('PageService', () => {
|
||||||
|
let service: PageService;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [PageService],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<PageService>(PageService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(service).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
24
server/src/core/page/page.service.ts
Normal file
24
server/src/core/page/page.service.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { PageRepository } from './repositories/page.repository';
|
||||||
|
import { CreatePageDto } from './dto/create-page.dto';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PageService {
|
||||||
|
constructor(private pageRepository: PageRepository) {}
|
||||||
|
|
||||||
|
async create(createPageDto: CreatePageDto) {
|
||||||
|
await this.pageRepository.save(createPageDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
async findById(pageId: string) {
|
||||||
|
return this.pageRepository.findById(pageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(pageId: string) {
|
||||||
|
return this.pageRepository.softDelete(pageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async forceDelete(pageId: string) {
|
||||||
|
return this.pageRepository.delete(pageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
server/src/core/page/repositories/page.repository.ts
Normal file
14
server/src/core/page/repositories/page.repository.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { DataSource, Repository } from 'typeorm';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { Page } from '../entities/page.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PageRepository extends Repository<Page> {
|
||||||
|
constructor(private dataSource: DataSource) {
|
||||||
|
super(Page, dataSource.createEntityManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
async findById(pageId: string) {
|
||||||
|
return this.findOneBy({ id: pageId });
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,16 +10,17 @@ import {
|
|||||||
import * as bcrypt from 'bcrypt';
|
import * as bcrypt from 'bcrypt';
|
||||||
import { Workspace } from '../../workspace/entities/workspace.entity';
|
import { Workspace } from '../../workspace/entities/workspace.entity';
|
||||||
import { WorkspaceUser } from '../../workspace/entities/workspace-user.entity';
|
import { WorkspaceUser } from '../../workspace/entities/workspace-user.entity';
|
||||||
|
import { Page } from '../../page/entities/page.entity';
|
||||||
|
|
||||||
@Entity('users')
|
@Entity('users')
|
||||||
export class User {
|
export class User {
|
||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ length: 255, nullable: true })
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@Column({ unique: true })
|
@Column({ length: 255, unique: true })
|
||||||
email: string;
|
email: string;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
@ -29,12 +30,12 @@ export class User {
|
|||||||
password: string;
|
password: string;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
avatar_url: string;
|
avatarUrl: string;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ length: 100, nullable: true })
|
||||||
locale: string;
|
locale: string;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ length: 300, nullable: true })
|
||||||
timezone: string;
|
timezone: string;
|
||||||
|
|
||||||
@Column({ type: 'jsonb', nullable: true })
|
@Column({ type: 'jsonb', nullable: true })
|
||||||
@ -43,7 +44,7 @@ export class User {
|
|||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
lastLoginAt: Date;
|
lastLoginAt: Date;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ length: 100, nullable: true })
|
||||||
lastLoginIp: string;
|
lastLoginIp: string;
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
@ -52,16 +53,15 @@ export class User {
|
|||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
|
|
||||||
@OneToMany(() => Workspace, (workspace) => workspace.creator, {
|
@OneToMany(() => Workspace, (workspace) => workspace.creator)
|
||||||
createForeignKeyConstraints: false,
|
|
||||||
})
|
|
||||||
workspaces: Workspace[];
|
workspaces: Workspace[];
|
||||||
|
|
||||||
@OneToMany(() => WorkspaceUser, (workspaceUser) => workspaceUser.user, {
|
@OneToMany(() => WorkspaceUser, (workspaceUser) => workspaceUser.user)
|
||||||
createForeignKeyConstraints: false,
|
|
||||||
})
|
|
||||||
workspaceUser: WorkspaceUser[];
|
workspaceUser: WorkspaceUser[];
|
||||||
|
|
||||||
|
@OneToMany(() => Page, (page) => page.creator)
|
||||||
|
createdPages;
|
||||||
|
|
||||||
toJSON() {
|
toJSON() {
|
||||||
delete this.password;
|
delete this.password;
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@ -15,28 +15,30 @@ export class WorkspaceInvitation {
|
|||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
workspaceId: string;
|
||||||
|
|
||||||
@ManyToOne(() => Workspace, {
|
@ManyToOne(() => Workspace, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
createForeignKeyConstraints: false,
|
|
||||||
})
|
})
|
||||||
@JoinColumn({ name: 'workspaceId' })
|
@JoinColumn({ name: 'workspaceId' })
|
||||||
workspace: Workspace;
|
workspace: Workspace;
|
||||||
|
|
||||||
@ManyToOne(() => User, {
|
@Column()
|
||||||
onDelete: 'SET NULL',
|
invitedById: string;
|
||||||
createForeignKeyConstraints: false,
|
|
||||||
})
|
@ManyToOne(() => User)
|
||||||
@JoinColumn({ name: 'invitedById' })
|
@JoinColumn({ name: 'invitedById' })
|
||||||
invitedBy: User;
|
invitedBy: User;
|
||||||
|
|
||||||
@Column({ type: 'varchar', length: 255 })
|
@Column({ length: 255 })
|
||||||
email: string;
|
email: string;
|
||||||
|
|
||||||
@Column({ type: 'varchar', length: 100, nullable: true })
|
@Column({ length: 100, nullable: true })
|
||||||
role?: string;
|
role: string;
|
||||||
|
|
||||||
@Column({ type: 'varchar', length: 100, nullable: true })
|
@Column({ length: 100, nullable: true })
|
||||||
status?: string;
|
status: string;
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
|
|||||||
@ -17,28 +17,26 @@ export class WorkspaceUser {
|
|||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
userId: string;
|
||||||
|
|
||||||
@ManyToOne(() => User, (user) => user.workspaceUser, {
|
@ManyToOne(() => User, (user) => user.workspaceUser, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
createForeignKeyConstraints: false,
|
|
||||||
})
|
})
|
||||||
@JoinColumn({ name: 'userId' })
|
@JoinColumn({ name: 'userId' })
|
||||||
user: User;
|
user: User;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
userId: string;
|
workspaceId: string;
|
||||||
|
|
||||||
@ManyToOne(() => Workspace, (workspace) => workspace.workspaceUser, {
|
@ManyToOne(() => Workspace, (workspace) => workspace.workspaceUsers, {
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
createForeignKeyConstraints: false,
|
|
||||||
})
|
})
|
||||||
@JoinColumn({ name: 'workspaceId' })
|
@JoinColumn({ name: 'workspaceId' })
|
||||||
workspace: Workspace;
|
workspace: Workspace;
|
||||||
|
|
||||||
@Column()
|
@Column({ length: 100, nullable: true })
|
||||||
workspaceId: string;
|
role: string;
|
||||||
|
|
||||||
@Column({ type: 'varchar', length: 100, nullable: true })
|
|
||||||
role?: string;
|
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
|
|||||||
@ -10,53 +10,60 @@ import {
|
|||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
import { User } from '../../user/entities/user.entity';
|
import { User } from '../../user/entities/user.entity';
|
||||||
import { WorkspaceUser } from './workspace-user.entity';
|
import { WorkspaceUser } from './workspace-user.entity';
|
||||||
|
import { Page } from '../../page/entities/page.entity';
|
||||||
|
import { WorkspaceInvitation } from './workspace-invitation.entity';
|
||||||
|
|
||||||
@Entity('workspaces')
|
@Entity('workspaces')
|
||||||
export class Workspace {
|
export class Workspace {
|
||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ length: 255, nullable: true })
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@Column({ type: 'text', nullable: true })
|
@Column({ type: 'text', nullable: true })
|
||||||
description?: string;
|
description: string;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ length: 255, nullable: true })
|
||||||
logo?: string;
|
logo: string;
|
||||||
|
|
||||||
@Column({ unique: true })
|
@Column({ length: 255, unique: true })
|
||||||
hostname: string;
|
hostname: string;
|
||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ length: 255, nullable: true })
|
||||||
customDomain?: string;
|
customDomain: string;
|
||||||
|
|
||||||
@Column({ type: 'boolean', default: true })
|
@Column({ type: 'boolean', default: true })
|
||||||
enableInvite: boolean;
|
enableInvite: boolean;
|
||||||
|
|
||||||
@Column({ type: 'text', unique: true, nullable: true })
|
@Column({ length: 255, unique: true, nullable: true })
|
||||||
inviteCode?: string;
|
inviteCode: string;
|
||||||
|
|
||||||
@Column({ type: 'jsonb', nullable: true })
|
@Column({ type: 'jsonb', nullable: true })
|
||||||
settings?: any;
|
settings: any;
|
||||||
|
|
||||||
@ManyToOne(() => User, (user) => user.workspaces, {
|
|
||||||
createForeignKeyConstraints: false,
|
|
||||||
})
|
|
||||||
@JoinColumn({ name: 'creatorId' })
|
|
||||||
creator: User;
|
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
creatorId: string;
|
creatorId: string;
|
||||||
|
|
||||||
|
@ManyToOne(() => User, (user) => user.workspaces)
|
||||||
|
@JoinColumn({ name: 'creatorId' })
|
||||||
|
creator: User;
|
||||||
|
|
||||||
@CreateDateColumn()
|
@CreateDateColumn()
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
|
|
||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
|
|
||||||
@OneToMany(() => WorkspaceUser, (workspaceUser) => workspaceUser.workspace, {
|
@OneToMany(() => WorkspaceUser, (workspaceUser) => workspaceUser.workspace)
|
||||||
createForeignKeyConstraints: false,
|
workspaceUsers: WorkspaceUser[];
|
||||||
})
|
|
||||||
workspaceUser: WorkspaceUser[];
|
@OneToMany(
|
||||||
|
() => WorkspaceInvitation,
|
||||||
|
(workspaceInvitation) => workspaceInvitation.workspace,
|
||||||
|
)
|
||||||
|
workspaceInvitations: WorkspaceInvitation[];
|
||||||
|
|
||||||
|
@OneToMany(() => Page, (page) => page.workspace)
|
||||||
|
pages: Page[];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user