Share - WIP

This commit is contained in:
Philipinho
2025-04-15 12:45:26 +01:00
parent 8dff3e2240
commit 418e61614c
32 changed files with 820 additions and 52 deletions

View File

@ -212,7 +212,7 @@ export class PageService {
trx,
);
const pageIds = await this.pageRepo
.getPageAndDescendants(rootPage.id)
.getPageAndDescendants(rootPage.id, { includeContent: false })
.then((pages) => pages.map((page) => page.id));
// The first id is the root page id
if (pageIds.length > 1) {

View File

@ -140,4 +140,14 @@ export class ShareController {
await this.shareRepo.deleteShare(share.id);
}
@Public()
@HttpCode(HttpStatus.OK)
@Post('/tree')
async getSharePageTree(
@Body() dto: ShareIdDto,
@AuthWorkspace() workspace: Workspace,
) {
return this.shareService.getShareTree(dto.shareId, workspace.id);
}
}

View File

@ -34,6 +34,23 @@ export class ShareService {
private readonly tokenService: TokenService,
) {}
async getShareTree(shareId: string, workspaceId: string) {
const share = await this.shareRepo.findById(shareId);
if (!share || share.workspaceId !== workspaceId) {
throw new NotFoundException('Share not found');
}
if (share.includeSubPages) {
const pageList = await this.pageRepo.getPageAndDescendants(share.pageId, {
includeContent: false,
});
return { share, pageTree: pageList };
} else {
return { share, pageTree: [] };
}
}
async createShare(opts: {
authUserId: string;
workspaceId: string;

View File

@ -26,7 +26,10 @@ export async function up(db: Kysely<any>): Promise<void> {
col.notNull().defaultTo(sql`now()`),
)
.addColumn('deleted_at', 'timestamptz', (col) => col)
.addUniqueConstraint('shares_key_unique', ['key'])
.addUniqueConstraint('shares_key_workspace_id_unique', [
'key',
'workspace_id',
])
.execute();
}

View File

@ -211,7 +211,10 @@ export class PageRepo {
).as('contributors');
}
async getPageAndDescendants(parentPageId: string) {
async getPageAndDescendants(
parentPageId: string,
opts: { includeContent: boolean },
) {
return this.db
.withRecursive('page_hierarchy', (db) =>
db
@ -221,11 +224,12 @@ export class PageRepo {
'slugId',
'title',
'icon',
'content',
'position',
'parentPageId',
'spaceId',
'workspaceId',
])
.$if(opts?.includeContent, (qb) => qb.select('content'))
.where('id', '=', parentPageId)
.unionAll((exp) =>
exp
@ -235,11 +239,12 @@ export class PageRepo {
'p.slugId',
'p.title',
'p.icon',
'p.content',
'p.position',
'p.parentPageId',
'p.spaceId',
'p.workspaceId',
])
.$if(opts?.includeContent, (qb) => qb.select('content'))
.innerJoin('page_hierarchy as ph', 'p.parentPageId', 'ph.id'),
),
)

View File

@ -131,6 +131,7 @@ export class ShareRepo {
const query = this.db
.selectFrom('shares')
.select(this.baseFields)
.select((eb) => this.withPage(eb))
.select((eb) => this.withSpace(eb))
.select((eb) => this.withCreator(eb))
.where('spaceId', 'in', userSpaceIds)
@ -146,6 +147,15 @@ export class ShareRepo {
return result;
}
withPage(eb: ExpressionBuilder<DB, 'shares'>) {
return jsonObjectFrom(
eb
.selectFrom('pages')
.select(['pages.id', 'pages.title', 'pages.slugId', 'pages.icon'])
.whereRef('pages.id', '=', 'shares.pageId'),
).as('page');
}
withSpace(eb: ExpressionBuilder<DB, 'shares'>) {
return jsonObjectFrom(
eb

View File

@ -27,7 +27,10 @@ import { EditorState } from '@tiptap/pm/state';
// eslint-disable-next-line @typescript-eslint/no-require-imports
import slugify = require('@sindresorhus/slugify');
import { EnvironmentService } from '../environment/environment.service';
import { getAttachmentIds, getProsemirrorContent } from '../../common/helpers/prosemirror/utils';
import {
getAttachmentIds,
getProsemirrorContent,
} from '../../common/helpers/prosemirror/utils';
@Injectable()
export class ExportService {
@ -87,7 +90,9 @@ export class ExportService {
}
async exportPageWithChildren(pageId: string, format: string) {
const pages = await this.pageRepo.getPageAndDescendants(pageId);
const pages = await this.pageRepo.getPageAndDescendants(pageId, {
includeContent: true,
});
if (!pages || pages.length === 0) {
throw new BadRequestException('No pages to export');