diff --git a/app/components/DuplicateDialog.tsx b/app/components/DuplicateDialog.tsx index 2a6992ad6..95785ec44 100644 --- a/app/components/DuplicateDialog.tsx +++ b/app/components/DuplicateDialog.tsx @@ -19,9 +19,17 @@ function DuplicateDialog({ document, onSubmit }: Props) { const defaultTitle = t(`Copy of {{ documentName }}`, { documentName: document.title, }); + const [publish, setPublish] = React.useState(!!document.publishedAt); const [recursive, setRecursive] = React.useState(true); const [title, setTitle] = React.useState(defaultTitle); + const handlePublishChange = React.useCallback( + (ev: React.ChangeEvent) => { + setPublish(ev.target.checked); + }, + [] + ); + const handleRecursiveChange = React.useCallback( (ev: React.ChangeEvent) => { setRecursive(ev.target.checked); @@ -38,6 +46,7 @@ function DuplicateDialog({ document, onSubmit }: Props) { const handleSubmit = async () => { const result = await document.duplicate({ + publish, recursive, title, }); @@ -56,15 +65,26 @@ function DuplicateDialog({ document, onSubmit }: Props) { defaultValue={defaultTitle} /> {document.publishedAt && !document.isTemplate && ( - - - + <> + + + + + + + )} ); diff --git a/app/models/Document.ts b/app/models/Document.ts index c2b465ba7..048a50a27 100644 --- a/app/models/Document.ts +++ b/app/models/Document.ts @@ -509,8 +509,11 @@ export default class Document extends ParanoidModel { move = (collectionId: string, parentDocumentId?: string | undefined) => this.store.move(this.id, collectionId, parentDocumentId); - duplicate = (options?: { title?: string; recursive?: boolean }) => - this.store.duplicate(this, options); + duplicate = (options?: { + title?: string; + publish?: boolean; + recursive?: boolean; + }) => this.store.duplicate(this, options); @computed get pinned(): boolean { diff --git a/app/stores/DocumentsStore.ts b/app/stores/DocumentsStore.ts index 0391b824b..6b7a52881 100644 --- a/app/stores/DocumentsStore.ts +++ b/app/stores/DocumentsStore.ts @@ -567,6 +567,7 @@ export default class DocumentsStore extends Store { document: Document, options?: { title?: string; + publish?: boolean; recursive?: boolean; } ): Promise => { diff --git a/server/commands/documentDuplicator.test.ts b/server/commands/documentDuplicator.test.ts index 4c06e1d90..4816c7f82 100644 --- a/server/commands/documentDuplicator.test.ts +++ b/server/commands/documentDuplicator.test.ts @@ -26,6 +26,7 @@ describe("documentDuplicator", () => { expect(response[0].title).toEqual(original.title); expect(response[0].text).toEqual(original.text); expect(response[0].emoji).toEqual(original.emoji); + expect(response[0].publishedAt).toBeInstanceOf(Date); }); it("should duplicate document with title override", async () => { @@ -51,6 +52,7 @@ describe("documentDuplicator", () => { expect(response[0].title).toEqual("New title"); expect(response[0].text).toEqual(original.text); expect(response[0].emoji).toEqual(original.emoji); + expect(response[0].publishedAt).toBeInstanceOf(Date); }); it("should duplicate child documents with recursive=true", async () => { @@ -81,4 +83,29 @@ describe("documentDuplicator", () => { expect(response).toHaveLength(2); }); + + it("should duplicate existing document as draft", async () => { + const user = await buildUser(); + const original = await buildDocument({ + userId: user.id, + teamId: user.teamId, + }); + + const response = await sequelize.transaction((transaction) => + documentDuplicator({ + document: original, + collection: original.collection, + transaction, + publish: false, + user, + ip, + }) + ); + + expect(response).toHaveLength(1); + expect(response[0].title).toEqual(original.title); + expect(response[0].text).toEqual(original.text); + expect(response[0].emoji).toEqual(original.emoji); + expect(response[0].publishedAt).toBeNull(); + }); }); diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index 07d94457c..3c80f20f3 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -197,6 +197,7 @@ "Viewed {{ timeAgo }}": "Viewed {{ timeAgo }}", "Copy of {{ documentName }}": "Copy of {{ documentName }}", "Title": "Title", + "Published": "Published", "Include nested documents": "Include nested documents", "Emoji Picker": "Emoji Picker", "Remove": "Remove",