diff --git a/packages/nocodb/src/interface/Jobs.ts b/packages/nocodb/src/interface/Jobs.ts index dc35529997..60b720ec5d 100644 --- a/packages/nocodb/src/interface/Jobs.ts +++ b/packages/nocodb/src/interface/Jobs.ts @@ -1,4 +1,5 @@ import type { AttachmentResType, PublicAttachmentScope, SupportedExportCharset, UserType } from 'nocodb-sdk'; + import type { NcContext, NcRequest } from '~/interface/config'; export const JOBS_QUEUE = 'jobs'; @@ -115,6 +116,7 @@ export interface DuplicateBaseJobData extends JobData { excludeData?: boolean; excludeViews?: boolean; excludeHooks?: boolean; + excludeComments?: boolean; }; } @@ -127,6 +129,7 @@ export interface DuplicateModelJobData extends JobData { excludeData?: boolean; excludeViews?: boolean; excludeHooks?: boolean; + excludeComments?: boolean; }; } diff --git a/packages/nocodb/src/models/Comment.ts b/packages/nocodb/src/models/Comment.ts index 9d4b2666dd..7446f8b9a9 100644 --- a/packages/nocodb/src/models/Comment.ts +++ b/packages/nocodb/src/models/Comment.ts @@ -41,6 +41,23 @@ export default class Comment implements CommentType { return comment && new Comment(comment); } + public static async listByModel( + context: NcContext, + fk_model_id: string, + ncMeta = Noco.ncMeta, + ): Promise { + const commentList = await ncMeta + .knex(MetaTable.COMMENTS) + .select(`${MetaTable.COMMENTS}.*`) + .where('fk_model_id', fk_model_id) + .where(function () { + this.whereNull('is_deleted').orWhere('is_deleted', '!=', true); + }) + .orderBy('created_at', 'asc'); + + return commentList.map((comment) => new Comment(comment)); + } + public static async list( context: NcContext, { diff --git a/packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts b/packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts index 4dd4b379d3..825fa36040 100644 --- a/packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts +++ b/packages/nocodb/src/modules/jobs/jobs/export-import/duplicate.processor.ts @@ -52,6 +52,7 @@ export class DuplicateProcessor { const excludeData = options?.excludeData || false; const excludeHooks = options?.excludeHooks || false; const excludeViews = options?.excludeViews || false; + const excludeComments = options?.excludeComments || excludeData || false; const base = await Base.get(context, baseId); const dupProject = await Base.get(context, dupProjectId); @@ -79,6 +80,7 @@ export class DuplicateProcessor { excludeViews, excludeHooks, excludeData, + excludeComments, }); elapsedTime( @@ -157,6 +159,7 @@ export class DuplicateProcessor { const excludeData = options?.excludeData || false; const excludeHooks = options?.excludeHooks || false; const excludeViews = options?.excludeViews || false; + const excludeComments = options?.excludeComments || excludeData || false; const base = await Base.get(context, baseId); const source = await Source.get(context, sourceId); @@ -184,6 +187,7 @@ export class DuplicateProcessor { excludeViews, excludeHooks, excludeData, + excludeComments, }) )[0]; diff --git a/packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts b/packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts index 06214a8059..fd9ca73dd6 100644 --- a/packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts +++ b/packages/nocodb/src/modules/jobs/jobs/export-import/export.service.ts @@ -7,7 +7,7 @@ import { elapsedTime, initTime } from '../../helpers'; import type { BaseModelSqlv2 } from '~/db/BaseModelSqlv2'; import type { NcContext } from '~/interface/config'; import type { LinkToAnotherRecordColumn } from '~/models'; -import { Base, Filter, Hook, Model, Source, View } from '~/models'; +import { Base, Comment, Filter, Hook, Model, Source, View } from '~/models'; import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2'; import { getViewAndModelByAliasOrId, @@ -36,6 +36,7 @@ export class ExportService { excludeViews?: boolean; excludeHooks?: boolean; excludeData?: boolean; + excludeComments?: boolean; }, ) { const { modelIds } = param; @@ -43,6 +44,8 @@ export class ExportService { const excludeData = param?.excludeData || false; const excludeViews = param?.excludeViews || false; const excludeHooks = param?.excludeHooks || false; + const excludeComments = + param?.excludeComments || param?.excludeData || false; const serializedModels = []; @@ -377,6 +380,30 @@ export class ExportService { } } + const searializedComments = []; + + if (!excludeComments) { + const comments = await Comment.listByModel(context, model.id); + + for (const comment of comments) { + idMap.set(comment.id, `${idMap.get(model.id)}::${comment.id}`); + + searializedComments.push({ + id: idMap.get(comment.id), + fk_model_id: idMap.get(comment.fk_model_id), + row_id: comment.row_id, + comment: comment.comment, + parent_comment_id: comment.parent_comment_id + ? idMap.get(comment.parent_comment_id) + : null, + created_by: comment.created_by, + resolved_by: comment.resolved_by, + created_by_email: comment.created_by_email, + resolved_by_email: comment.resolved_by_email, + }); + } + } + serializedModels.push({ model: { id: idMap.get(model.id), @@ -443,6 +470,7 @@ export class ExportService { view: view.view, })), hooks: serializedHooks, + comments: searializedComments, }); } diff --git a/packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts b/packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts index ef5a6b3854..3644306618 100644 --- a/packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts +++ b/packages/nocodb/src/modules/jobs/jobs/export-import/import.service.ts @@ -19,7 +19,7 @@ import type { View, } from '~/models'; import type { NcContext, NcRequest } from '~/interface/config'; -import { Hook } from '~/models'; +import { Comment, Hook } from '~/models'; import { Base, Column, Model, Source } from '~/models'; import { findWithIdentifier, @@ -80,8 +80,15 @@ export class ImportService { baseId: string; sourceId: string; data: - | { models: { model: any; views: any[]; hooks?: any[] }[] } - | { model: any; views: any[]; hooks?: any[] }[]; + | { + models: { + model: any; + views: any[]; + hooks?: any[]; + comments?: any[]; + }[]; + } + | { model: any; views: any[]; hooks?: any[]; comments?: any[] }[]; req: NcRequest; externalModels?: Model[]; existingModel?: Model; @@ -282,6 +289,29 @@ export class ImportService { } } + // create comments + for (const data of param.data) { + if (param.existingModel) break; + if (!data?.comments) break; + const modelData = data.model; + const commentsData = data.comments; + + const table = tableReferences.get(modelData.id); + + for (const commentD of commentsData) { + const comment = await Comment.insert( + context, + withoutId({ + ...commentD, + fk_model_id: table.id, + parent_comment_id: idMap.get(commentD.parent_comment_id), + }), + ); + + idMap.set(commentD.id, comment.id); + } + } + elapsedTime(hrTime, 'create tables with static columns', 'importModels'); const referencedColumnSet = [];