From 8a537b86df70d2ef9f3394abef1047903805eae7 Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Mon, 15 Oct 2018 11:21:51 -0500 Subject: [PATCH] Backups download zip with folders for all content types --- .../app/services/archiveManager.js | 46 +++++++++++++++---- .../directives/account-menu.html.haml | 2 +- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/app/assets/javascripts/app/services/archiveManager.js b/app/assets/javascripts/app/services/archiveManager.js index 6a6204b44..a064611b1 100644 --- a/app/assets/javascripts/app/services/archiveManager.js +++ b/app/assets/javascripts/app/services/archiveManager.js @@ -27,12 +27,12 @@ class ArchiveManager { } } this.__itemsData(items, keys, authParams).then((data) => { - this.__downloadData(data, `SN Archive - ${new Date()}.txt`); + let modifier = encrypted ? "Encrypted" : "Decrypted"; + this.__downloadData(data, `Standard Notes ${modifier} Backup - ${this.__formattedDate()}.txt`); // download as zipped plain text files if(!keys) { - var notes = this.modelManager.allItemsMatchingTypes(["Note"]); - this.__downloadZippedNotes(notes); + this.__downloadZippedItems(items); } }) } @@ -41,6 +41,16 @@ class ArchiveManager { Private */ + __formattedDate() { + var string = `${new Date()}`; + // Match up to the first parenthesis, i.e do not include '(Central Standard Time)' + var matches = string.match(/^(.*?) \(/); + if(matches.length >= 2) { + return matches[1] + } + return string; + } + async __itemsData(items, keys, authParams) { let data = await this.modelManager.getJSONDataForItems(items, keys, authParams); let blobData = new Blob([data], {type: 'text/json'}); @@ -64,24 +74,40 @@ class ArchiveManager { } } - __downloadZippedNotes(notes) { + __downloadZippedItems(items) { this.__loadZip(() => { zip.createWriter(new zip.BlobWriter("application/zip"), (zipWriter) => { var index = 0; let nextFile = () => { - var note = notes[index]; - var blob = new Blob([note.text], {type: 'text/plain'}); + var item = items[index]; + var name, contents; - var title = note.safeTitle().replace(/\//g, "").replace(/\\+/g, ""); + if(item.content_type == "Note") { + name = item.content.title; + contents = item.content.text; + } else { + name = item.content_type; + contents = JSON.stringify(item.content, null, 2); + } - zipWriter.add(`${title}-${note.uuid}.txt`, new zip.BlobReader(blob), () => { + var blob = new Blob([contents], {type: 'text/plain'}); + + var filePrefix = name.replace(/\//g, "").replace(/\\+/g, ""); + var fileSuffix = `-${item.uuid.split("-")[0]}.txt` + + // Standard max filename length is 255. Slice the note name down to allow filenameEnd + filePrefix = filePrefix.slice(0, (255 - fileSuffix.length)); + + let fileName = `${item.content_type}/${filePrefix}${fileSuffix}` + + zipWriter.add(fileName, new zip.BlobReader(blob), () => { index++; - if(index < notes.length) { + if(index < items.length) { nextFile(); } else { zipWriter.close((blob) => { - this.__downloadData(blob, `Notes Txt Archive - ${new Date()}.zip`) + this.__downloadData(blob, `Standard Notes Backup - ${this.__formattedDate()}.zip`); zipWriter = null; }); } diff --git a/app/assets/templates/directives/account-menu.html.haml b/app/assets/templates/directives/account-menu.html.haml index a64c6bb8a..f0fb6736c 100644 --- a/app/assets/templates/directives/account-menu.html.haml +++ b/app/assets/templates/directives/account-menu.html.haml @@ -142,7 +142,7 @@ Decrypted .button-group - .button.info{"ng-click" => "downloadDataArchive()", "ng-class" => "{'mt-5' : !user}"} + .button.info{"ng-click" => "downloadDataArchive()"} .label Download Backup %label.button.info