You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-06-30 23:44:55 +02:00
All: Also duplicate resources when duplicating a note
Ref: https://github.com/laurent22/joplin/issues/5796
This commit is contained in:
@ -7,6 +7,8 @@ import Folder from './Folder';
|
|||||||
import Note from './Note';
|
import Note from './Note';
|
||||||
import Tag from './Tag';
|
import Tag from './Tag';
|
||||||
import ItemChange from './ItemChange';
|
import ItemChange from './ItemChange';
|
||||||
|
import Resource from './Resource';
|
||||||
|
import { ResourceEntity } from '../services/database/types';
|
||||||
const ArrayUtils = require('../ArrayUtils.js');
|
const ArrayUtils = require('../ArrayUtils.js');
|
||||||
|
|
||||||
async function allItems() {
|
async function allItems() {
|
||||||
@ -143,6 +145,27 @@ describe('models/Note', function() {
|
|||||||
expect(duplicatedNoteTags.length).toBe(2);
|
expect(duplicatedNoteTags.length).toBe(2);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should also duplicate resources when duplicating a note', (async () => {
|
||||||
|
const folder = await Folder.save({ title: 'folder' });
|
||||||
|
let note = await Note.save({ title: 'note', parent_id: folder.id });
|
||||||
|
await shim.attachFileToNote(note, `${supportDir}/photo.jpg`);
|
||||||
|
|
||||||
|
const resource = (await Resource.all())[0];
|
||||||
|
expect((await Resource.all()).length).toBe(1);
|
||||||
|
|
||||||
|
const duplicatedNote = await Note.duplicate(note.id);
|
||||||
|
|
||||||
|
const resources: ResourceEntity[] = await Resource.all();
|
||||||
|
expect(resources.length).toBe(2);
|
||||||
|
|
||||||
|
const duplicatedResource = resources.find(r => r.id !== resource.id);
|
||||||
|
|
||||||
|
note = await Note.load(note.id);
|
||||||
|
|
||||||
|
expect(note.body).toContain(resource.id);
|
||||||
|
expect(duplicatedNote.body).toContain(duplicatedResource.id);
|
||||||
|
}));
|
||||||
|
|
||||||
it('should delete a set of notes', (async () => {
|
it('should delete a set of notes', (async () => {
|
||||||
const folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
const noOfNotes = 20;
|
const noOfNotes = 20;
|
||||||
|
@ -595,23 +595,36 @@ export default class Note extends BaseItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async duplicate(noteId: string, options: any = null) {
|
private static async duplicateNoteResources(noteBody: string): Promise<string> {
|
||||||
|
const resourceIds = await this.linkedResourceIds(noteBody);
|
||||||
|
let newBody: string = noteBody;
|
||||||
|
|
||||||
|
for (const resourceId of resourceIds) {
|
||||||
|
const newResource = await Resource.duplicateResource(resourceId);
|
||||||
|
const regex = new RegExp(resourceId, 'gi');
|
||||||
|
newBody = newBody.replace(regex, newResource.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async duplicate(noteId: string, options: any = null) {
|
||||||
const changes = options && options.changes;
|
const changes = options && options.changes;
|
||||||
const uniqueTitle = options && options.uniqueTitle;
|
const uniqueTitle = options && options.uniqueTitle;
|
||||||
|
|
||||||
const originalNote = await Note.load(noteId);
|
const originalNote: NoteEntity = await Note.load(noteId);
|
||||||
if (!originalNote) throw new Error(`Unknown note: ${noteId}`);
|
if (!originalNote) throw new Error(`Unknown note: ${noteId}`);
|
||||||
|
|
||||||
const newNote = Object.assign({}, originalNote);
|
const newNote = Object.assign({}, originalNote);
|
||||||
const fieldsToReset = ['id', 'created_time', 'updated_time', 'user_created_time', 'user_updated_time'];
|
const fieldsToReset = ['id', 'created_time', 'updated_time', 'user_created_time', 'user_updated_time'];
|
||||||
|
|
||||||
for (const field of fieldsToReset) {
|
for (const field of fieldsToReset) {
|
||||||
delete newNote[field];
|
delete (newNote as any)[field];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const n in changes) {
|
for (const n in changes) {
|
||||||
if (!changes.hasOwnProperty(n)) continue;
|
if (!changes.hasOwnProperty(n)) continue;
|
||||||
newNote[n] = changes[n];
|
(newNote as any)[n] = changes[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uniqueTitle) {
|
if (uniqueTitle) {
|
||||||
@ -619,6 +632,8 @@ export default class Note extends BaseItem {
|
|||||||
newNote.title = title;
|
newNote.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newNote.body = await this.duplicateNoteResources(newNote.body);
|
||||||
|
|
||||||
const newNoteSaved = await this.save(newNote);
|
const newNoteSaved = await this.save(newNote);
|
||||||
const originalTags = await Tag.tagsByNoteId(noteId);
|
const originalTags = await Tag.tagsByNoteId(noteId);
|
||||||
for (const tagToAdd of originalTags) {
|
for (const tagToAdd of originalTags) {
|
||||||
|
@ -364,7 +364,7 @@ export default class Resource extends BaseItem {
|
|||||||
return await this.fsDriver().readFile(Resource.fullPath(resource), encoding);
|
return await this.fsDriver().readFile(Resource.fullPath(resource), encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async duplicateResource(resourceId: string) {
|
public static async duplicateResource(resourceId: string): Promise<ResourceEntity> {
|
||||||
const resource = await Resource.load(resourceId);
|
const resource = await Resource.load(resourceId);
|
||||||
const localState = await Resource.localState(resource);
|
const localState = await Resource.localState(resource);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user