Skip to content

Commit f717ed9

Browse files
authored
Merge pull request #1923 from ehhc/Moving_Note_With_Attachment
Move note with attachment to different storage Fix for #1788
2 parents 2a6d950 + d3091a5 commit f717ed9

File tree

7 files changed

+115
-64
lines changed

7 files changed

+115
-64
lines changed

browser/main/SideNav/StorageItem.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import i18n from 'browser/lib/i18n'
1414

1515
const { remote } = require('electron')
1616
const { Menu, dialog } = remote
17+
const escapeStringRegexp = require('escape-string-regexp')
18+
const path = require('path')
1719

1820
class StorageItem extends React.Component {
1921
constructor (props) {
@@ -201,7 +203,7 @@ class StorageItem extends React.Component {
201203
createdNoteData.forEach((newNote) => {
202204
dispatch({
203205
type: 'MOVE_NOTE',
204-
originNote: noteData.find((note) => note.content === newNote.content),
206+
originNote: noteData.find((note) => note.content === newNote.oldContent),
205207
note: newNote
206208
})
207209
})
@@ -223,7 +225,8 @@ class StorageItem extends React.Component {
223225
const { folderNoteMap, trashedSet } = data
224226
const SortableStorageItemChild = SortableElement(StorageItemChild)
225227
const folderList = storage.folders.map((folder, index) => {
226-
const isActive = !!(location.pathname.match(new RegExp('\/storages\/' + storage.key + '\/folders\/' + folder.key)))
228+
let folderRegex = new RegExp(escapeStringRegexp(path.sep) + 'storages' + escapeStringRegexp(path.sep) + storage.key + escapeStringRegexp(path.sep) + 'folders' + escapeStringRegexp(path.sep) + folder.key)
229+
const isActive = !!(location.pathname.match(folderRegex))
227230
const noteSet = folderNoteMap.get(storage.key + '-' + folder.key)
228231

229232
let noteCount = 0
@@ -253,7 +256,7 @@ class StorageItem extends React.Component {
253256
)
254257
})
255258

256-
const isActive = location.pathname.match(new RegExp('\/storages\/' + storage.key + '$'))
259+
const isActive = location.pathname.match(new RegExp(escapeStringRegexp(path.sep) + 'storages' + escapeStringRegexp(path.sep) + storage.key + '$'))
257260

258261
return (
259262
<div styleName={isFolded ? 'root--folded' : 'root'}

browser/main/lib/dataApi/attachmentManagement.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const fs = require('fs')
33
const path = require('path')
44
const findStorage = require('browser/lib/findStorage')
55
const mdurl = require('mdurl')
6+
const fse = require('fs-extra')
67
const escapeStringRegexp = require('escape-string-regexp')
78
const sander = require('sander')
89

@@ -181,6 +182,28 @@ function getAbsolutePathsOfAttachmentsInContent (markdownContent, storagePath) {
181182
return result
182183
}
183184

185+
/**
186+
* @description Moves the attachments of the current note to the new location.
187+
* Returns a modified version of the given content so that the links to the attachments point to the new note key.
188+
* @param {String} oldPath Source of the note to be moved
189+
* @param {String} newPath Destination of the note to be moved
190+
* @param {String} noteKey Old note key
191+
* @param {String} newNoteKey New note key
192+
* @param {String} noteContent Content of the note to be moved
193+
* @returns {String} Modified version of noteContent in which the paths of the attachments are fixed
194+
*/
195+
function moveAttachments (oldPath, newPath, noteKey, newNoteKey, noteContent) {
196+
const src = path.join(oldPath, DESTINATION_FOLDER, noteKey)
197+
const dest = path.join(newPath, DESTINATION_FOLDER, newNoteKey)
198+
if (fse.existsSync(src)) {
199+
fse.moveSync(src, dest)
200+
}
201+
if (noteContent) {
202+
return noteContent.replace(new RegExp(STORAGE_FOLDER_PLACEHOLDER + escapeStringRegexp(path.sep) + noteKey, 'g'), path.join(STORAGE_FOLDER_PLACEHOLDER, newNoteKey))
203+
}
204+
return noteContent
205+
}
206+
184207
/**
185208
* @description Deletes all :storage and noteKey references from the given input.
186209
* @param input Input in which the references should be deleted
@@ -256,6 +279,7 @@ module.exports = {
256279
removeStorageAndNoteReferences,
257280
deleteAttachmentFolder,
258281
deleteAttachmentsNotPresentInNote,
282+
moveAttachments,
259283
STORAGE_FOLDER_PLACEHOLDER,
260284
DESTINATION_FOLDER
261285
}

browser/main/lib/dataApi/copyImage.js

Lines changed: 0 additions & 38 deletions
This file was deleted.

browser/main/lib/dataApi/moveNote.js

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const CSON = require('@rokt33r/season')
66
const keygen = require('browser/lib/keygen')
77
const sander = require('sander')
88
const { findStorage } = require('browser/lib/findStorage')
9+
const attachmentManagement = require('./attachmentManagement')
910

1011
function moveNote (storageKey, noteKey, newStorageKey, newFolderKey) {
1112
let oldStorage, newStorage
@@ -63,36 +64,20 @@ function moveNote (storageKey, noteKey, newStorageKey, newFolderKey) {
6364
noteData.key = newNoteKey
6465
noteData.storage = newStorageKey
6566
noteData.updatedAt = new Date()
67+
noteData.oldContent = noteData.content
6668

6769
return noteData
6870
})
69-
.then(function moveImages (noteData) {
70-
if (oldStorage.path === newStorage.path) return noteData
71-
72-
const searchImagesRegex = /!\[.*\]\(:storage\/(.+)\)/gi
73-
let match = searchImagesRegex.exec(noteData.content)
74-
75-
const moveTasks = []
76-
while (match != null) {
77-
const [, filename] = match
78-
const oldPath = path.join(oldStorage.path, 'attachments', filename)
79-
const newPath = path.join(newStorage.path, 'attachments', filename)
80-
// TODO: ehhc: attachmentManagement
81-
moveTasks.push(
82-
sander.copyFile(oldPath).to(newPath)
83-
.then(() => {
84-
fs.unlinkSync(oldPath)
85-
})
86-
)
87-
88-
// find next occurence
89-
match = searchImagesRegex.exec(noteData.content)
71+
.then(function moveAttachments (noteData) {
72+
if (oldStorage.path === newStorage.path) {
73+
return noteData
9074
}
9175

92-
return Promise.all(moveTasks).then(() => noteData)
76+
noteData.content = attachmentManagement.moveAttachments(oldStorage.path, newStorage.path, noteKey, newNoteKey, noteData.content)
77+
return noteData
9378
})
9479
.then(function writeAndReturn (noteData) {
95-
CSON.writeFileSync(path.join(newStorage.path, 'notes', noteData.key + '.cson'), _.omit(noteData, ['key', 'storage']))
80+
CSON.writeFileSync(path.join(newStorage.path, 'notes', noteData.key + '.cson'), _.omit(noteData, ['key', 'storage', 'oldContent']))
9681
return noteData
9782
})
9883
.then(function deleteOldNote (data) {

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@
5757
"codemirror-mode-elixir": "^1.1.1",
5858
"electron-config": "^0.2.1",
5959
"electron-gh-releases": "^2.0.2",
60+
"escape-string-regexp": "^1.0.5",
6061
"filenamify": "^2.0.0",
6162
"flowchart.js": "^1.6.5",
6263
"font-awesome": "^4.3.0",
64+
"fs-extra": "^5.0.0",
6365
"i18n-2": "^0.7.2",
6466
"iconv-lite": "^0.4.19",
6567
"immutable": "^3.8.1",

tests/dataApi/attachmentManagement.test.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const findStorage = require('browser/lib/findStorage')
77
jest.mock('unique-slug')
88
const uniqueSlug = require('unique-slug')
99
const mdurl = require('mdurl')
10+
const fse = require('fs-extra')
1011
const sander = require('sander')
1112

1213
const systemUnderTest = require('browser/main/lib/dataApi/attachmentManagement')
@@ -326,3 +327,59 @@ it('should test that deleteAttachmentsNotPresentInNote does not delete reference
326327
}
327328
expect(fsUnlinkCallArguments.includes(path.join(attachmentFolderPath, dummyFilesInFolder[0]))).toBe(false)
328329
})
330+
331+
it('should test that moveAttachments moves attachments only if the source folder existed', function () {
332+
fse.existsSync = jest.fn(() => false)
333+
fse.moveSync = jest.fn()
334+
335+
const oldPath = 'oldPath'
336+
const newPath = 'newPath'
337+
const oldNoteKey = 'oldNoteKey'
338+
const newNoteKey = 'newNoteKey'
339+
const content = ''
340+
341+
const expectedSource = path.join(oldPath, systemUnderTest.DESTINATION_FOLDER, oldNoteKey)
342+
343+
systemUnderTest.moveAttachments(oldPath, newPath, oldNoteKey, newNoteKey, content)
344+
expect(fse.existsSync).toHaveBeenCalledWith(expectedSource)
345+
expect(fse.moveSync).not.toHaveBeenCalled()
346+
})
347+
348+
it('should test that moveAttachments moves attachments to the right destination', function () {
349+
fse.existsSync = jest.fn(() => true)
350+
fse.moveSync = jest.fn()
351+
352+
const oldPath = 'oldPath'
353+
const newPath = 'newPath'
354+
const oldNoteKey = 'oldNoteKey'
355+
const newNoteKey = 'newNoteKey'
356+
const content = ''
357+
358+
const expectedSource = path.join(oldPath, systemUnderTest.DESTINATION_FOLDER, oldNoteKey)
359+
const expectedDestination = path.join(newPath, systemUnderTest.DESTINATION_FOLDER, newNoteKey)
360+
361+
systemUnderTest.moveAttachments(oldPath, newPath, oldNoteKey, newNoteKey, content)
362+
expect(fse.existsSync).toHaveBeenCalledWith(expectedSource)
363+
expect(fse.moveSync).toHaveBeenCalledWith(expectedSource, expectedDestination)
364+
})
365+
366+
it('should test that moveAttachments returns a correct modified content version', function () {
367+
fse.existsSync = jest.fn()
368+
fse.moveSync = jest.fn()
369+
370+
const oldPath = 'oldPath'
371+
const newPath = 'newPath'
372+
const oldNoteKey = 'oldNoteKey'
373+
const newNoteKey = 'newNoteKey'
374+
const testInput =
375+
'Test input' +
376+
'![' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + oldNoteKey + path.sep + 'image.jpg](imageName}) \n' +
377+
'[' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + oldNoteKey + path.sep + 'pdf.pdf](pdf})'
378+
const expectedOutput =
379+
'Test input' +
380+
'![' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + newNoteKey + path.sep + 'image.jpg](imageName}) \n' +
381+
'[' + systemUnderTest.STORAGE_FOLDER_PLACEHOLDER + path.sep + newNoteKey + path.sep + 'pdf.pdf](pdf})'
382+
383+
const actualContent = systemUnderTest.moveAttachments(oldPath, newPath, oldNoteKey, newNoteKey, testInput)
384+
expect(actualContent).toBe(expectedOutput)
385+
})

yarn.lock

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3637,6 +3637,14 @@ fs-extra@^1.0.0:
36373637
jsonfile "^2.1.0"
36383638
klaw "^1.0.0"
36393639

3640+
fs-extra@^5.0.0:
3641+
version "5.0.0"
3642+
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd"
3643+
dependencies:
3644+
graceful-fs "^4.1.2"
3645+
jsonfile "^4.0.0"
3646+
universalify "^0.1.0"
3647+
36403648
36413649
version "2.10.1"
36423650
resolved "https://registry.yarnpkg.com/fs-plus/-/fs-plus-2.10.1.tgz#3204781d7840611e6364e7b6fb058c96327c5aa5"
@@ -5309,6 +5317,12 @@ jsonfile@^2.0.0, jsonfile@^2.1.0:
53095317
optionalDependencies:
53105318
graceful-fs "^4.1.6"
53115319

5320+
jsonfile@^4.0.0:
5321+
version "4.0.0"
5322+
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
5323+
optionalDependencies:
5324+
graceful-fs "^4.1.6"
5325+
53125326
jsonify@~0.0.0:
53135327
version "0.0.0"
53145328
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
@@ -8734,6 +8748,10 @@ unique-temp-dir@^1.0.0:
87348748
os-tmpdir "^1.0.1"
87358749
uid2 "0.0.3"
87368750

8751+
universalify@^0.1.0:
8752+
version "0.1.1"
8753+
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"
8754+
87378755
unpipe@~1.0.0:
87388756
version "1.0.0"
87398757
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"

0 commit comments

Comments
 (0)