diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f4c945..ba14d09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## not released +## v1.4.1 (2024-03-10) + +- Fix: Don't show `There is no Data to export` on empty profiles and automatic backups #71 + ## v1.4.0 (2024-02-22) - Changes that are required for the Joplin default plugin diff --git a/FULLRESTORE.md b/FULLRESTORE.md new file mode 100644 index 0000000..8c69eef --- /dev/null +++ b/FULLRESTORE.md @@ -0,0 +1,57 @@ +# Full Joplin restore + +A Joplin Export (JEX) file created by the Backup plugin can be used to perform a full restore of all notebooks, notes and attachments. This should be carefully undertaken as a mistake could cause the notes in the clients and on the sync server to be duplicated. To avoid duplication it also requires that any clients attached to the server are cleared of their note data and are then re-synced after the restore. For those with large note collections and numerous, large files attached to the notes, this could take a long time for each client. Essentially undertaking a full restore is a disaster recovery exercise. If you wish to just re-upload your notes to the server or re-download your notes from the server please please refer to the Joplin settings for Synchronisation under "Show Advanced Settings". + +> When Joplin imports a JEX backup file **it treats every notebook and note within that backup as a new item**. All the items in the backup will get new unique reference numbers (however links between notes will be maintained). If the client the backup is being restored to already contains all or some of the notebooks and notes in the backup they will be duplicated. +> +> A JEX backup file **does not** contain any note history. It contains the notebooks, notes and attachments as they were at the time the backup was made. + +The following options for a restore are described here: + +- [Full Restore - Without fully resetting the Joplin clients](#full-restore---without-fully-resetting-the-joplin-clients) +- [Full Restore - Fully resetting the Joplin clients](#full-restore---fully-resetting-the-joplin-clients) + +## Full Restore - Without fully resetting the Joplin clients + +With this method the existing link to the synchronisation cloud storage server will be preserved and used. If End to End Encryption (E2EE) has been enabled the settings will be preserved and used. Any customisation and installed plugins will be retained. + +- Identify the Joplin desktop client that has the best Internet connection as this will be the primary machine for the restore. +- Place a copy of the Joplin backup file on that machine. +- Open the Joplin client on the primary machine and delete all notes and notebooks. +- Empty the Joplin client trash folder (Joplin 3.0+). +- Sync the Joplin client so that all the notes are deleted on the cloud storage server. +- When the above sync is complete, sync any other clients so that all the notebooks and notes they contain are deleted. +- In case the cloud storage server has limits on how much data can be transferred at once it is suggested that all clients other than the one on the primary machine are shut down. +- When all clients are empty move to the primary machine and import the backup (`File > Import > JEX - Joplin Export File`). +- Sync the client to the cloud storage server. If you have a large collection of notes and attachments this may tale some time. +- Once complete, start each client in turn and sync. The restored notes will be downloaded. If you have a large collection of notes and attachments this may tale some time. +- If you are certain that the cloud provider will not limit connections or download speed if a large volume of transfers are made, the other clients could be synced at the same time. + +## Full Restore - Fully resetting the Joplin clients + +With this method the existing link to the synchronisation cloud storage server will be lost. If End to End Encryption (E2EE) has been enabled the settings will be lost. Any customisation and installed plugins will be lost but **copies are stored with the JEX file in the backup archive**. + +- Identify the Joplin desktop client that has the best Internet connection as this will be the primary machine for the restore. +- Place a copy of the Joplin backup file on that machine. +- If possible, open the Joplin client on the primary machine and delete all notes and notebooks. +- Empty the Joplin client trash folder (Joplin 3.0+). +- Sync the Joplin client so that all the notes are deleted on the cloud storage server, or access the cloud storage server directly and delete the files in the folder Joplin uses for syncing. +- Completely shut down all clients (`File > Quit`), including the primary machine. +- On Windows machines delete, rename or move the folder `C:\Users\username\.config\joplin-desktop` +- On Linux and Mac machines delete, rename or move the folder `/home/username/.config/joplin-desktop` +- On mobile devices use the mobile OS's App settings to delete the Joplin app data and cache. +- Start the Joplin client on the primary machine. +- Joplin will recreate the `joplin-desktop` folder and the client will be as if just installed with only the "Welcome" notes. +- There will be no sync settings or E2EE settings. +- Connect the primary machine to the cloud storage server using the required credentials. +- Sync to the server (this will be just the "Welcome" notes and so should be very quick). +- If required set up E2EE and re-sync (this will be just the "Welcome" notes and so should be very quick). +- For every other client, open Joplin, delete the "Welcome" notes and connect to the cloud storage server being used for sync. +- This will download the encrypted notes created by the primary machine, so when prompted by Joplin enter the E2EE password that was previously set on the primary machine (this will be just the "Welcome" notes and so should be very quick). +- Once it is confirmed that all clients are connected and that E2EE is working, fully shut down all clients except on the primary machine. +- Open the Joplin client on the primary machine and delete the "Welcome" notes / notebook. +- Empty the Joplin client trash folder (Joplin 3.0+). +- Import the backup (`File > Import > JEX - Joplin Export File`). +- Sync the client to the cloud storage server. If you have a large collection of notes and attachments this may tale some time. +- Once complete, start each client in turn and sync. The restored notes will be downloaded. If you have a large collection of notes and attachments this may tale some time. +- If you are certain that the cloud provider will not limit connections or download speed if a large volume of transfers are made, the other clients could be synced at the same time. diff --git a/README.md b/README.md index e626475..0d0c493 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ A plugin to extend Joplin with a manual and automatic backup function. - [Settings](#settings) - [Notes](#notes) - [Restore a singel note](#restore-a-singel-note) + - [Full Joplin restore](#full-joplin-restore) - [FAQ](#faq) - [Internal Joplin links betwen notes are lost](#internal-joplin-links-betwen-notes-are-lost) - [Combine multiple JEX Files to one](#combine-multiple-jex-files-to-one) @@ -29,8 +30,8 @@ A plugin to extend Joplin with a manual and automatic backup function. - [Are Note History Revisions backed up?](#are-note-history-revisions-backed-up) - [Are all Joplin profiles backed up?](#are-all-joplin-profiles-backed-up) - [The Joplin build-in version of the plugin cannot be updated](#the-joplin-build-in-version-of-the-plugin-cannot-be-updated) + - [Can I use a Backup to speed up first Joplin sync?](#can-i-use-a-backup-to-speed-up-first-joplin-sync) - [Changelog](#changelog) -- [Links](#links) @@ -112,6 +113,10 @@ If the notebook in which the note was located already exists in your Joplin, the 7. Switch back to your orginal Joplin profil via `File > Switch profile > Default` 8. Import the exported note via `File > Import > JEX - Joplin Export File` and select the file from step 6 +### Full Joplin restore + +See the guide for a [Full Joplin restore](FULLRESTORE.md) + ## FAQ ### Internal Joplin links betwen notes are lost @@ -135,7 +140,7 @@ The file names in the archive correspond to the Joplin internal IDs. ### Are Note History (Revisions) backed up? -The note history and file versions (revisions) are not included in the backup. +A JEX backup file **does not** contain any note history (revisions). It contains the notebooks, notes and attachments as they were at the time the backup was made. ### Are all Joplin profiles backed up? @@ -146,13 +151,12 @@ Profiles that are not active are not backed up, even if a backup has been config Yes, the build-in version only gets updates with Joplin updates, but can be replaced as described in the [Installation](#installation) step. -## Changelog +### Can I use a Backup to speed up first Joplin sync? -See [CHANGELOG.md](CHANGELOG.md) +No, because all items in the backup will get newunique IDs are assigned in Joplin during the import (however links between notes will be maintained). +If this device is then synchronized with a synchronization target in which other clients already synchronize with the same notes, all notes are then available multiple times on the devices. +Therefore, the same note is then available with different IDs in Joplin. -## Links +## Changelog -- [Joplin - Getting started with plugin development](https://joplinapp.org/api/get_started/plugins/) -- [Joplin - Plugin API reference](https://joplinapp.org/api/references/plugin_api/classes/joplin.html) -- [Joplin - Data API reference](https://joplinapp.org/api/references/rest_api/) -- [Joplin - Plugin examples](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins) +See [CHANGELOG.md](CHANGELOG.md) diff --git a/__test__/backup.test.ts b/__test__/backup.test.ts index 2f3f9f4..4101b1f 100644 --- a/__test__/backup.test.ts +++ b/__test__/backup.test.ts @@ -29,6 +29,7 @@ let spyOnLogError = null; let spyOnShowError = null; let spyOnSaveBackupInfo = null; let spyOnDataGet = null; +let spyOnIsThereData = null; const spyOnsSettingsValue = jest.spyOn(joplin.settings, "value"); const spyOnGlobalValue = jest.spyOn(joplin.settings, "globalValue"); @@ -1119,6 +1120,15 @@ describe("Backup", function () { }); describe("create backup readme", () => { + beforeEach(async () => { + spyOnIsThereData = jest + .spyOn(backup, "isThereData") + .mockImplementation(() => Promise.resolve(true)); + }); + afterEach(async () => { + spyOnIsThereData.mockRestore(); + }); + it.each([ { backupRetention: 1, createSubfolderPerProfile: false }, { backupRetention: 2, createSubfolderPerProfile: false }, diff --git a/package-lock.json b/package-lock.json index bc4f08a..dc5cd8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "joplin-plugin-backup", - "version": "1.4.0", + "version": "1.4.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "joplin-plugin-backup", - "version": "1.4.0", + "version": "1.4.1", "license": "MIT", "dependencies": { "@types/i18n": "^0.13.6", diff --git a/package.json b/package.json index 7c29698..35ce947 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "joplin-plugin-backup", - "version": "1.4.0", + "version": "1.4.1", "scripts": { "dist": "webpack --env joplin-plugin-config=buildMain && webpack --env joplin-plugin-config=buildExtraScripts && webpack --env joplin-plugin-config=createArchive", "prepare": "npm run dist && husky install", diff --git a/src/Backup.ts b/src/Backup.ts index 183b3b7..91d6c79 100644 --- a/src/Backup.ts +++ b/src/Backup.ts @@ -504,6 +504,14 @@ class Backup { } public async start(showDoneMsg: boolean = false) { + // Prevent error message for empty profile on automatic backup + // https://github.com/JackGruber/joplin-plugin-backup/issues/71 + // https://github.com/laurent22/joplin/issues/10046 + if (showDoneMsg == false && (await this.isThereData()) === false) { + this.log.warn(`Empty Joplin profile (No notes), skipping backup`); + return; + } + if (this.backupStartTime === null) { this.backupStartTime = new Date(); @@ -1281,6 +1289,22 @@ class Backup { }); return true; } + + private async isThereData(): Promise { + let check = await joplin.data.get(["notes"], { + fields: "title, id, updated_time", + order_by: "updated_time", + order_dir: "DESC", + limit: 1, + page: 1, + }); + + if (check.items.length > 0) { + return true; + } else { + return false; + } + } } export { Backup, i18n }; diff --git a/src/manifest.json b/src/manifest.json index 0af6002..4075dc9 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 1, "id": "io.github.jackgruber.backup", "app_min_version": "2.1.3", - "version": "1.4.0", + "version": "1.4.1", "name": "Backup", "description": "Plugin to create manual and automatic backups.", "author": "JackGruber",