Skip to content

Commit 039d477

Browse files
committed
feat: add automatic backups #23
1 parent 1c92dfe commit 039d477

File tree

6 files changed

+111
-15
lines changed

6 files changed

+111
-15
lines changed

app-src/scripts/_app.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
.run(initGlobalShortcuts)
4545
.run(showWelcomeDialog)
4646
.run(goToWorkViewIfTasks)
47-
.run(initPollAutomaticBackups);
47+
.run(iniAutomaticBackupsIfEnabled);
4848

4949
/* @ngInject */
5050
function configMarked(markedProvider) {
@@ -226,11 +226,9 @@
226226
}
227227

228228
/* @ngInject */
229-
function initPollAutomaticBackups(BACKUP_POLL_INTERVAL, $interval, IS_ELECTRON) {
229+
function iniAutomaticBackupsIfEnabled(IS_ELECTRON, AppStorage) {
230230
if (IS_ELECTRON) {
231-
//$interval(() => {
232-
//
233-
//}, BACKUP_POLL_INTERVAL)
231+
AppStorage.initBackupsIfEnabled();
234232
}
235233
}
236234
})();

app-src/scripts/constants.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@
9898
togglePlay: 'y',
9999
},
100100
config: {
101+
automaticBackups: {
102+
isEnabled: false,
103+
path: '~/backup-{date}.json',
104+
intervalInSeconds: 6
105+
},
101106
isTakeABreakEnabled: false,
102107
takeABreakMinWorkingTime: undefined,
103108
isAutoStartNextTask: true,

app-src/scripts/main/global-services/app-storage-s.js

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313

1414
class AppStorage {
1515
/* @ngInject */
16-
constructor(LS_DEFAULTS, SAVE_APP_STORAGE_POLL_INTERVAL, TMP_FIELDS, $interval, $rootScope, ON_DEMAND_LS_FIELDS, ON_DEMAND_LS_FIELDS_FOR_PROJECT) {
16+
constructor(LS_DEFAULTS, SAVE_APP_STORAGE_POLL_INTERVAL, TMP_FIELDS, $interval, $rootScope, ON_DEMAND_LS_FIELDS, ON_DEMAND_LS_FIELDS_FOR_PROJECT, IS_ELECTRON) {
1717
this.PROJECTS_KEY = 'projects';
1818
this.LS_DEFAULTS = LS_DEFAULTS;
1919
this.TMP_FIELDS = TMP_FIELDS;
2020
this.SAVE_APP_STORAGE_POLL_INTERVAL = SAVE_APP_STORAGE_POLL_INTERVAL;
2121
this.ON_DEMAND_LS_FIELDS = ON_DEMAND_LS_FIELDS;
2222
this.ON_DEMAND_LS_FIELDS_FOR_PROJECT = ON_DEMAND_LS_FIELDS_FOR_PROJECT;
23+
this.IS_ELECTRON = IS_ELECTRON;
2324
this.$rootScope = $rootScope;
2425
this.$interval = $interval;
2526
this.serializer = angular.toJson;
@@ -36,19 +37,72 @@
3637
//}, 5);
3738
}
3839

40+
initBackupsIfEnabled() {
41+
if (!this.IS_ELECTRON
42+
|| !this.$rootScope.r.config.automaticBackups
43+
|| !this.$rootScope.r.config.automaticBackups.isEnabled) {
44+
return;
45+
}
46+
const fs = require('fs');
47+
const interval = parseInt(this.$rootScope.r.config.automaticBackups.intervalInSeconds, 10) * 1000;
48+
49+
this.$interval(() => {
50+
if (!this.$rootScope.r.config.automaticBackups
51+
|| !this.$rootScope.r.config.automaticBackups.isEnabled
52+
|| parseInt(this.$rootScope.r.config.automaticBackups.intervalInSeconds, 10) === 0
53+
|| !this.$rootScope.r.config.automaticBackups.path
54+
|| !this.$rootScope.r.config.automaticBackups.path.trim().length > 0
55+
) {
56+
return;
57+
}
58+
59+
const now = window.moment();
60+
const path = this.$rootScope.r.config.automaticBackups.path
61+
.replace('{date}', now.format('YYYY-MM-DD'))
62+
.replace('{unix}', now.format('x'));
63+
64+
this.saveToFileSystem(fs, path);
65+
}, interval);
66+
}
67+
68+
saveToFileSystem(fs, path) {
69+
const data = angular.copy(this.getCurrentAppState());
70+
71+
// also add projects data
72+
data[this.PROJECTS_KEY] = this.getProjects();
73+
74+
fs.writeFile(path, JSON.stringify(data), function(err) {
75+
if (err) {
76+
console.error(err);
77+
} else {
78+
console.log('Backup to ' + path + ' completed');
79+
}
80+
});
81+
}
82+
3983
setupPollingForSavingCurrentState() {
4084
this.$interval(() => {
4185
this.saveToLs();
4286
}, this.SAVE_APP_STORAGE_POLL_INTERVAL);
4387
}
4488

45-
saveToLs() {
46-
for (let key in this.$rootScope.r) {
89+
// gets the current state of the app excluding tmp variables and the projects
90+
getCurrentAppState() {
91+
const currentState = {};
92+
for (let key in this.LS_DEFAULTS) {
4793
const isNoTmpField = this.TMP_FIELDS.indexOf(key) === -1;
48-
if (this.$rootScope.r.hasOwnProperty(key) && isNoTmpField && key !== this.PROJECTS_KEY) {
49-
this.saveLsItem(this.$rootScope.r[key], key);
94+
if (this.LS_DEFAULTS.hasOwnProperty(key) && isNoTmpField && key !== this.PROJECTS_KEY) {
95+
currentState[key] = this.$rootScope.r[key];
5096
}
5197
}
98+
return currentState;
99+
}
100+
101+
saveToLs() {
102+
const currentState = this.getCurrentAppState();
103+
for (let key in currentState) {
104+
this.saveLsItem(currentState[key], key);
105+
}
52106
}
53107

54108
getProjects() {

app-src/scripts/routes/settings/settings-c.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
<section class="config-section"
2929
md-whiteframe="2">
30-
<backup-settings></backup-settings>
30+
<backup-settings settings="r.config.automaticBackups"></backup-settings>
3131
</section>
3232

3333

app-src/scripts/settings/backup-settings/backup-settings-d.html

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
<h2 class="md-title">
22
<ng-md-icon icon="swap_vert"></ng-md-icon>
3-
Make/Restore Backup
3+
Backup and Sync
44
</h2>
55

66
<help-section>
7-
<p>Here you can download all your data as <strong>JSON</strong> export for backups, but also to use it in a different context (e.g. you might want to export your projects in the browser and import them into the desktop version).</p>
7+
<p>Here you can download all your data as
8+
<strong>JSON</strong> export for backups, but also to use it in a different context (e.g. you might want to export your projects in the browser and import them into the desktop version).
9+
</p>
810
<p>The import expects valid json to be copied into the text area.
911
<strong>NOTE: Once you hit the import button all your current settings and data will be overwritten!</strong></p>
12+
13+
<section ng-if="vm.IS_ELECTRON">
14+
<p>There is also the option to do
15+
<strong>automatic backups</strong>. You can choose an interval in seconds of how often the backup should occur and a custom destination to where the backup should be saved. You can use `{unix}` and `{date}` inside the path string to add output a unix timestamp or a date at this location of the string. E.g. `/mypath/{date}.json` will save your data to `/mypath/2017-12-12.json.
16+
</p>
17+
</section>
1018
</help-section>
1119

1220
<a class="md-raised md-button md-ink-ripple"
@@ -43,3 +51,31 @@ <h2 class="md-title">
4351
class="md-raised md-primary">Import settings
4452
</md-button>
4553
</form>
54+
55+
56+
<section ng-if="vm.IS_ELECTRON">
57+
<h3 class="md-caption">Automatic Backups</h3>
58+
<div>
59+
<md-switch ng-model="vm.settings.isEnabled"
60+
aria-label="Enable automatic backups">
61+
Enable automatic backups
62+
</md-switch>
63+
</div>
64+
65+
<p><strong>NOTE:</strong> Changes to automated backup settings require you to restart the application to take effect.
66+
</p>
67+
68+
<div ng-show="vm.settings.isEnabled">
69+
<md-input-container class="md-block">
70+
<label>Interval in seconds to make backups</label>
71+
<input type="number"
72+
ng-model="vm.settings.intervalInSeconds">
73+
</md-input-container>
74+
<md-input-container class="md-block">
75+
<label>Path to backup (e.g. ~/backup-{date}.json)</label>
76+
<input type="text"
77+
ng-model="vm.settings.path">
78+
</md-input-container>
79+
80+
</div>
81+
</section>

app-src/scripts/settings/backup-settings/backup-settings-d.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,16 @@
2020
controller: BackupSettingsCtrl,
2121
controllerAs: 'vm',
2222
restrict: 'E',
23-
scope: {}
23+
scope: {
24+
settings: '='
25+
}
2426
};
2527
}
2628

2729
/* @ngInject */
28-
function BackupSettingsCtrl($rootScope, AppStorage) {
30+
function BackupSettingsCtrl($rootScope, AppStorage, IS_ELECTRON) {
2931
let vm = this;
32+
vm.IS_ELECTRON = IS_ELECTRON;
3033

3134
// import/export stuff
3235
vm.importSettings = (uploadSettingsTextarea) => {

0 commit comments

Comments
 (0)