diff --git a/src/api/form.template/form.template.controller.ts b/src/api/form.template/form.template.controller.ts index 1f1aa20..744a1af 100644 --- a/src/api/form.template/form.template.controller.ts +++ b/src/api/form.template/form.template.controller.ts @@ -214,6 +214,28 @@ export class FormTemplateController { } }; + export = async (request: express.Request, response: express.Response) => { + try { + var id: uuid = await this._validator.requestParamAsUUID( + request, + 'id' + ); + const exportData = await this._service.export(id); + + const { filename, sourceFileLocation } + = await Helper.storeTemplateToFileLocally(exportData); + + var mimeType = Helper.getMimeType(sourceFileLocation); + response.setHeader('Content-type', mimeType); + response.setHeader('Content-disposition', 'attachment; filename=' + filename); + + var filestream = fs.createReadStream(sourceFileLocation); + filestream.pipe(response); + } catch (error) { + ResponseHandler.handleError(request, response, error); + } + }; + //#region Private Helper Methods @@ -378,6 +400,7 @@ export class FormTemplateController { } } + updateFavourite = async (request: express.Request, response: express.Response) => { try { const id = request.params.id; diff --git a/src/api/form.template/form.template.router.ts b/src/api/form.template/form.template.router.ts index 580de96..994537a 100644 --- a/src/api/form.template/form.template.router.ts +++ b/src/api/form.template/form.template.router.ts @@ -15,6 +15,7 @@ export const register = (app: express.Application): void => { router.get('/:id', context(`${contextBase}.GetById`), controller.getById); router.delete('/:id', context(`${contextBase}.Delete`), controller.delete); router.get('/:id/details', context(`${contextBase}.GetDetailsById`), controller.getDetailsById); + router.get('/:id/export', context(`${contextBase}.Export`), controller.export); router.put('/:id/favourites', context(`${contextBase}.UpdateFavourite`), controller.updateFavourite); app.use('/api/v1/form-templates', router); diff --git a/src/database/services/form.template.service.ts b/src/database/services/form.template.service.ts index 9d7d5a1..2d32e57 100644 --- a/src/database/services/form.template.service.ts +++ b/src/database/services/form.template.service.ts @@ -313,6 +313,96 @@ export class FormTemplateService extends BaseService { } }; + public export = async (id: uuid): Promise => { + try { + const template = await this._formTemplateRepository.findOne({ + where: { + id: id, + DeletedAt: IsNull(), + }, + relations: { + FormSections: { + FormFields: { + SkipLogic: { + Rules: { + FallbackRule: true, + BaseFallbackRuleEntity: true, + }, + }, + CalculateLogic: { + Rules: { + FallbackRule: true, + }, + }, + ValidateLogic: { + Rules: { + FallbackRule: true, + }, + }, + }, + }, + }, + order: { + FormSections: { + CreatedAt: "ASC", + FormFields: { + CreatedAt: "ASC", + }, + }, + }, + }); + + if (!template) { + ErrorHandler.throwNotFoundError('Form template not found!'); + } + + // Filter out deleted sections and fields + if (template.FormSections) { + template.FormSections = template.FormSections.filter( + (section) => section.DeletedAt === null + ); + + template.FormSections.forEach((section) => { + if (section.FormFields) { + section.FormFields = section.FormFields.filter( + (field) => field.DeletedAt === null + ); + } + }); + } + + // Map sections to hierarchical structure + const mappedSections = await this.mapSections(template.FormSections); + + // Populate operations for all form fields + await this.populateFormFieldsOperations(mappedSections); + + // Create export DTO + const exportDto: ExportFormTemplateDto = { + Template: { + id: template.id, + Title: template.Title, + Description: template.Description, + CurrentVersion: template.Version, + TenantCode: template.TenantId, + Type: template.Type as any, + DisplayCode: template.DisplayCode, + OwnerUserId: template.OwnerUserId, + RootSectionId: template.RootSectionId, + DefaultSectionNumbering: template.DefaultSectionNumbering, + CreatedAt: template.CreatedAt, + UpdatedAt: template.UpdatedAt, + Sections: mappedSections, + }, + }; + + return exportDto; + } catch (error) { + logger.error(`Error exporting form template: ${error.message}`); + ErrorHandler.throwInternalServerError(error.message, error); + } + }; + //#region Privates diff --git a/src/domain.types/form.template.domain.types.ts b/src/domain.types/form.template.domain.types.ts index 3ef5f31..933e3e7 100644 --- a/src/domain.types/form.template.domain.types.ts +++ b/src/domain.types/form.template.domain.types.ts @@ -85,7 +85,6 @@ export interface FormTemplateSearchResponseDto extends BaseSearchResults { } export interface ExportFormTemplateDto { - Sections: any; Template: TemplateDto; }