feat: space export (#506)

* wip

* Space export
* option to export pages with children
* include attachments in exports
* unified export UI

* cleanup

* fix: change export icon

* add export button to space settings

* cleanups

* export name
This commit is contained in:
Philip Okugbe
2024-11-30 19:47:22 +00:00
committed by GitHub
parent 9fa432dba9
commit fe83557767
20 changed files with 926 additions and 117 deletions

View File

@ -10,7 +10,7 @@ import {
UseGuards,
} from '@nestjs/common';
import { ExportService } from './export.service';
import { ExportPageDto } from './dto/export-dto';
import { ExportPageDto, ExportSpaceDto } from './dto/export-dto';
import { AuthUser } from '../../common/decorators/auth-user.decorator';
import { User } from '@docmost/db/types/entity.types';
import SpaceAbilityFactory from '../../core/casl/abilities/space-ability.factory';
@ -54,10 +54,28 @@ export class ImportController {
throw new ForbiddenException();
}
const rawContent = await this.exportService.exportPage(dto.format, page);
const fileExt = getExportExtension(dto.format);
const fileName = sanitize(page.title || 'Untitled') + fileExt;
const fileName = sanitize(page.title || 'untitled') + fileExt;
if (dto.includeChildren) {
const zipFileBuffer = await this.exportService.exportPageWithChildren(
dto.pageId,
dto.format,
);
const newName = fileName + '.zip';
res.headers({
'Content-Type': 'application/zip',
'Content-Disposition':
'attachment; filename="' + encodeURIComponent(newName) + '"',
});
res.send(zipFileBuffer);
return;
}
const rawContent = await this.exportService.exportPage(dto.format, page);
res.headers({
'Content-Type': getMimeType(fileExt),
@ -67,4 +85,34 @@ export class ImportController {
res.send(rawContent);
}
@UseGuards(JwtAuthGuard)
@HttpCode(HttpStatus.OK)
@Post('spaces/export')
async exportSpace(
@Body() dto: ExportSpaceDto,
@AuthUser() user: User,
@Res() res: FastifyReply,
) {
const ability = await this.spaceAbility.createForUser(user, dto.spaceId);
if (ability.cannot(SpaceCaslAction.Manage, SpaceCaslSubject.Page)) {
throw new ForbiddenException();
}
const exportFile = await this.exportService.exportSpace(
dto.spaceId,
dto.format,
dto.includeAttachments,
);
res.headers({
'Content-Type': 'application/zip',
'Content-Disposition':
'attachment; filename="' +
encodeURIComponent(sanitize(exportFile.fileName)) +
'"',
});
res.send(exportFile.fileBuffer);
}
}