From 9cc4683edf98fd0b3828df781baf8c1d53746d95 Mon Sep 17 00:00:00 2001 From: Umberto Russo Date: Sun, 10 Mar 2019 11:53:37 +0100 Subject: [PATCH 1/9] Added auto start feature --- main.ts | 14 ++++++++++++++ .../components/settings/settings.component.html | 13 +++++++++++++ src/app/components/settings/settings.component.ts | 8 ++++++-- src/assets/i18n/en.json | 4 ++++ src/assets/i18n/it.json | 4 ++++ 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/main.ts b/main.ts index f4767dd..f3efdd6 100644 --- a/main.ts +++ b/main.ts @@ -12,6 +12,8 @@ import * as path from 'path'; import * as url from 'url'; import * as Splashscreen from '@trodi/electron-splashscreen'; import * as contextMenuInternal from 'electron-context-menu'; +import * as fs from 'fs-extra'; +import {isUndefined} from 'util'; const {autoUpdater} = require('electron-updater'); const sugar = require('sugar'); @@ -121,6 +123,18 @@ function initIpc() { ipcMain.on('remove-process-to-kill', (event, processPid) => { sugar.Array.remove(awsCliProcesses, processPid); }); + + ipcMain.on('set-auto-start', (event, enableAutoStart) => { + enableAutoStart = Boolean(enableAutoStart); + setAutoStart(enableAutoStart); + }); +} + +function setAutoStart(enableAutoStart) { + app.setLoginItemSettings({ + openAtLogin: enableAutoStart, + path: app.getPath('exe') + }); } try { diff --git a/src/app/components/settings/settings.component.html b/src/app/components/settings/settings.component.html index 4672d85..a5dfb96 100644 --- a/src/app/components/settings/settings.component.html +++ b/src/app/components/settings/settings.component.html @@ -107,4 +107,17 @@

{{'PAGES.NOTIFICATIONS-SETTINGS.TITLE' | translate}}

+
+
+ +
+

{{'PAGES.APP-SETTINGS.TITLE' | translate}}

+
+

+ {{ 'PAGES.APP-SETTINGS.AUTOSTART' | translate }} +

+
+
+
+ diff --git a/src/app/components/settings/settings.component.ts b/src/app/components/settings/settings.component.ts index 99bfa95..c5c03a9 100644 --- a/src/app/components/settings/settings.component.ts +++ b/src/app/components/settings/settings.component.ts @@ -8,6 +8,7 @@ import {TranslateService} from '@ngx-translate/core'; import {MatChipInputEvent} from '@angular/material'; import {COMMA, ENTER} from '@angular/cdk/keycodes'; import {isUndefined} from 'util'; +import {ElectronService} from '../../providers/electron.service'; @Component({ selector: 'app-settings', @@ -37,7 +38,8 @@ export class SettingsComponent implements OnInit { emailSender: string, emailReceivers: string[], s3MaxConcurrentRequests: number, - s3MaxBandwidth: number + s3MaxBandwidth: number, + autoStart: boolean }; awsCliStatus: any; @@ -74,7 +76,8 @@ export class SettingsComponent implements OnInit { private appMenuService: AppMenuService, private aws: AwsService, private utilsService: UtilsService, - private translate: TranslateService + private translate: TranslateService, + private electronService: ElectronService ) { } @@ -101,6 +104,7 @@ export class SettingsComponent implements OnInit { save() { this.settingsService.save(this.settings); this.translate.use(this.settings.language); + this.electronService.ipcRenderer.send('set-auto-start', this.settings.autoStart); this.snackBar.open('Settings saved', '', { duration: 3000, verticalPosition: 'top', diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index dbe4526..220d25c 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -93,6 +93,10 @@ "SAVE": "Save", "LANGUAGE": "Language" }, + "APP-SETTINGS": { + "TITLE": "APP Settings", + "AUTOSTART": "Starts on OS boot" + }, "NOTIFICATIONS-SETTINGS": { "TITLE": "Notifications settings", "ALLOW": "Allow notifications", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index f82f2e1..6da9430 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -93,6 +93,10 @@ "SAVE": "Salva", "LANGUAGE": "Lingua" }, + "APP-SETTINGS": { + "TITLE": "Opzioni APP", + "AUTOSTART": "Esegui all'avvio del sistema operativo" + }, "NOTIFICATIONS-SETTINGS": { "TITLE": "Opzioni notifiche", "ALLOW": "Abilita notifiche", From 488b9cec5eeb79ec0cdd6774d7a963ef26a4789e Mon Sep 17 00:00:00 2001 From: Umberto Russo Date: Mon, 11 Mar 2019 00:24:24 +0100 Subject: [PATCH 2/9] Changed readme --- README.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index cf48bf0..623db54 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,13 @@

- AWS S3 Backup + AWS S3 Backup
+ Backup on AWS S3 ? Never been so easy!

-[![Make a pull request][prs-badge]][prs] -[![License](http://img.shields.io/badge/Licence-MIT-brightgreen.svg)](LICENSE) -[![Tested](https://img.shields.io/badge/tested%20on-Win%2010%20x64-brightgreen.svg)]() +

+ PR + MIT + Tested on Win 10 +

# Introduction @@ -91,8 +94,3 @@ Don't forget to deactivate the "Developer Tools" by commenting `win.webContents. |`npm run electron:linux`| Builds your application and creates an app consumable on linux system | |`npm run electron:windows`| On a Windows OS, builds your application and creates an app consumable in windows 32/64 bit systems | |`npm run electron:mac`| On a MAC OS, builds your application and generates a `.app` file of your application that can be run on Mac | - -[license-badge]: https://img.shields.io/badge/license-Apache2-blue.svg?style=flat -[license]: https://github.com/ulver2812/aws-s3-backup/LICENSE -[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square -[prs]: http://makeapullrequest.com From 53d3439ddb0a24ead7b767430cd7da96019b7ee6 Mon Sep 17 00:00:00 2001 From: Umberto Russo Date: Mon, 11 Mar 2019 00:25:12 +0100 Subject: [PATCH 3/9] Added app single instance check --- main.ts | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/main.ts b/main.ts index f3efdd6..08715cc 100644 --- a/main.ts +++ b/main.ts @@ -12,8 +12,6 @@ import * as path from 'path'; import * as url from 'url'; import * as Splashscreen from '@trodi/electron-splashscreen'; import * as contextMenuInternal from 'electron-context-menu'; -import * as fs from 'fs-extra'; -import {isUndefined} from 'util'; const {autoUpdater} = require('electron-updater'); const sugar = require('sugar'); @@ -22,6 +20,7 @@ const kill = require('tree-kill'); let win, serve, tray; const awsCliProcesses = []; const args = process.argv.slice(1); +let winIsHidden = false; serve = args.some(val => val === '--serve'); function createWindow() { @@ -81,6 +80,7 @@ function createWindow() { win.on('close', (event) => { win.hide(); + winIsHidden = true; event.preventDefault(); }); } @@ -102,6 +102,7 @@ function createTray() { tray.setContextMenu(contextMenu); tray.on('click', () => { win.show(); + winIsHidden = false; }); } @@ -137,8 +138,31 @@ function setAutoStart(enableAutoStart) { }); } +function checkSingleInstance() { + // TODO: da cambiare dopo l'aggiornamento a electron 4 + // to make singleton instance + const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => { + // Someone tried to run a second instance, we should focus our window. + if (win) { + if (win.isMinimized()) { + win.restore(); + win.focus(); + } else if (winIsHidden) { + win.show(); + } + } + }); + + if (isSecondInstance) { + app.quit(); + return; + } +} + try { + checkSingleInstance(); + // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. From 030a8516967c1339b253d3398de0666572a8081a Mon Sep 17 00:00:00 2001 From: Umberto Russo Date: Mon, 11 Mar 2019 12:52:20 +0100 Subject: [PATCH 4/9] Added time and data unit conversion Added time (minutes to hours ) and data (KB/s to Mb/s) unit conversion --- src/app/components/edit-job/edit-job.component.html | 4 ++-- src/app/components/edit-job/edit-job.component.ts | 7 +++++++ src/app/components/jobs-list/jobs-list.component.html | 4 ++-- src/app/components/jobs-list/jobs-list.component.ts | 5 +++++ src/app/components/new-job/new-job.component.html | 4 ++-- src/app/components/new-job/new-job.component.ts | 7 +++++++ src/app/components/settings/settings.component.html | 4 ++-- src/app/components/settings/settings.component.ts | 9 +++++++++ src/app/interfaces/ijob.ts | 2 ++ src/app/models/job.model.ts | 5 +++++ src/assets/i18n/en.json | 1 + src/assets/i18n/it.json | 1 + 12 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/app/components/edit-job/edit-job.component.html b/src/app/components/edit-job/edit-job.component.html index 05de98e..f0a74ff 100644 --- a/src/app/components/edit-job/edit-job.component.html +++ b/src/app/components/edit-job/edit-job.component.html @@ -89,10 +89,10 @@

{{ 'PAGES.EDIT-JOB.FIELDS.SCHEDULE-ERR' | translate }}

- - {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-MINUTES' | translate}} + {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-MINUTES' | translate}} = {{maxExecutionHours}} {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-HOURS' | translate}} {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-HINT' | translate}} diff --git a/src/app/components/edit-job/edit-job.component.ts b/src/app/components/edit-job/edit-job.component.ts index 7b5ce5b..636ac9f 100644 --- a/src/app/components/edit-job/edit-job.component.ts +++ b/src/app/components/edit-job/edit-job.component.ts @@ -48,6 +48,8 @@ export class EditJobComponent implements OnInit { days = this.cronService.days; daysOfMonth = this.cronService.daysOfMonth; + maxExecutionHours: string; + constructor( private route: ActivatedRoute, private router: Router, @@ -91,6 +93,7 @@ export class EditJobComponent implements OnInit { this.jobDayOfMonth = this.job.period.dayOfMonth; this.jobTime = this.job.period.time; this.jobMaxExecutionTime = this.job.getMaxExecutionTimeFormatted(); + this.convertMinutesToHours(this.jobMaxExecutionTime); }); Promise.resolve().then(() => { @@ -195,4 +198,8 @@ export class EditJobComponent implements OnInit { } } + convertMinutesToHours(minutes) { + const res = minutes / 60; + this.maxExecutionHours = res.toFixed(2); + } } diff --git a/src/app/components/jobs-list/jobs-list.component.html b/src/app/components/jobs-list/jobs-list.component.html index a4610fe..73dce6d 100644 --- a/src/app/components/jobs-list/jobs-list.component.html +++ b/src/app/components/jobs-list/jobs-list.component.html @@ -7,7 +7,7 @@

{{ 'PAGES.JOB-LIST.TITLE' | translate }}


- + @@ -21,7 +21,7 @@

{{job.name}}

- {{ 'PAGES.JOB-LIST.MAX-EXECUTION-TIME' | translate }}: {{job.getMaxExecutionTimeFormatted()}} - {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-MINUTES' | translate}} + {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-MINUTES' | translate}} = {{maxExecutionTimeHours[jobIndex]}} {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-HOURS' | translate}} - {{ 'PAGES.JOB-LIST.NEXT-RUN' | translate }}: {{scheduledJobs[job.id]}} diff --git a/src/app/components/jobs-list/jobs-list.component.ts b/src/app/components/jobs-list/jobs-list.component.ts index c4bd27a..89ab1d0 100644 --- a/src/app/components/jobs-list/jobs-list.component.ts +++ b/src/app/components/jobs-list/jobs-list.component.ts @@ -24,6 +24,7 @@ export class JobsListComponent implements OnInit { jobType = JobType; jobs: Job[]; scheduledJobs: string[]; + maxExecutionTimeHours: string[]; constructor( private jobService: JobsService, @@ -41,6 +42,10 @@ export class JobsListComponent implements OnInit { ngOnInit() { this.appMenuService.changeMenuPage('PAGES.JOB-LIST.TITLE'); this.jobs = this.jobService.getJobs(); + this.maxExecutionTimeHours = []; + this.jobs.forEach((element) => { + this.maxExecutionTimeHours.push(element.getMaxExecutionTimeFormattedHours()); + }); this.scheduledJobs = this.jobScheduler.getScheduledJobsFormattedTime(); } diff --git a/src/app/components/new-job/new-job.component.html b/src/app/components/new-job/new-job.component.html index 0183233..cbd5882 100644 --- a/src/app/components/new-job/new-job.component.html +++ b/src/app/components/new-job/new-job.component.html @@ -90,8 +90,8 @@

{{ 'PAGES.EDIT-JOB.FIELDS.SCHEDULE-ERR' | translate }}

- {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-MINUTES' | translate}} + [disabled]="job.type === jobType.Live" (ngModelChange)="convertMinutesToHours($event)" (ngModelChange)="job.setMaxExecutionTime($event)"> + {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-MINUTES' | translate}} = {{maxExecutionHours}} {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-HOURS' | translate}} {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-HINT' | translate}} diff --git a/src/app/components/new-job/new-job.component.ts b/src/app/components/new-job/new-job.component.ts index 2d239a2..03929dd 100644 --- a/src/app/components/new-job/new-job.component.ts +++ b/src/app/components/new-job/new-job.component.ts @@ -28,6 +28,7 @@ export class NewJobComponent implements OnInit { jobDay = []; jobDayOfMonth = []; jobTime = '00:00'; + maxExecutionHours: string; months = this.cronService.months; days = this.cronService.days; @@ -52,6 +53,7 @@ export class NewJobComponent implements OnInit { this.jobStartDateFormatted = this.job.getStartDateFormatted(); this.jobEndDateFormatted = this.job.getEndDateFormatted(); this.jobMaxExecutionTimeFormatted = this.job.getMaxExecutionTimeFormatted(); + this.convertMinutesToHours(this.jobMaxExecutionTimeFormatted); } saveNewJob() { @@ -112,4 +114,9 @@ export class NewJobComponent implements OnInit { } return false; } + + convertMinutesToHours(minutes) { + const res = minutes / 60; + this.maxExecutionHours = res.toFixed(2); + } } diff --git a/src/app/components/settings/settings.component.html b/src/app/components/settings/settings.component.html index a5dfb96..58dd9f0 100644 --- a/src/app/components/settings/settings.component.html +++ b/src/app/components/settings/settings.component.html @@ -51,8 +51,8 @@

{{'PAGES.S3-SETTINGS.TITLE' | translate}}

- - KB/s  + + KB/s = {{bandwidthMbs}} {{'PAGES.S3-SETTINGS.MAX-BANDWIDTH-DESC' | translate}} diff --git a/src/app/components/settings/settings.component.ts b/src/app/components/settings/settings.component.ts index c5c03a9..d7588a2 100644 --- a/src/app/components/settings/settings.component.ts +++ b/src/app/components/settings/settings.component.ts @@ -46,6 +46,8 @@ export class SettingsComponent implements OnInit { awsCliCredentials: any; spinner = true; + bandwidthMbs: string; + regions = [ {id: 'eu-west-1', value: 'EU (Ireland)'}, {id: 'eu-west-2', value: 'EU (London)'}, @@ -99,6 +101,8 @@ export class SettingsComponent implements OnInit { this.checkSettings(); this.utilsService.checkInternetConnection(); + + this.convertS3MaxBandwidth(this.settings.s3MaxBandwidth); } save() { @@ -152,4 +156,9 @@ export class SettingsComponent implements OnInit { this.settings.emailReceivers.splice(index, 1); } } + + convertS3MaxBandwidth(bandwidthKBs) { + const res = (bandwidthKBs / 1000 ) * 8; + this.bandwidthMbs = res.toFixed(2) + 'Mb/s'; + } } diff --git a/src/app/interfaces/ijob.ts b/src/app/interfaces/ijob.ts index 660821b..8b05a16 100644 --- a/src/app/interfaces/ijob.ts +++ b/src/app/interfaces/ijob.ts @@ -27,5 +27,7 @@ export interface IJob { getMaxExecutionTimeFormatted(): number; + getMaxExecutionTimeFormattedHours(): string; + setMaxExecutionTime(formattedMaxExecutionTime); } diff --git a/src/app/models/job.model.ts b/src/app/models/job.model.ts index ca10996..19cf79a 100644 --- a/src/app/models/job.model.ts +++ b/src/app/models/job.model.ts @@ -65,6 +65,11 @@ export class Job implements IJob { return (this.maxExecutionTime / 1000) / 60; } + getMaxExecutionTimeFormattedHours(): string { + const res = this.getMaxExecutionTimeFormatted() / 60; + return res.toFixed(2); + } + setMaxExecutionTime(formattedMaxExecutionTime) { this.maxExecutionTime = sugar.Number.minutes(formattedMaxExecutionTime); } diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 220d25c..64946f3 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -48,6 +48,7 @@ "SELECT-FILES-DIRS": "Selected Files and Directories", "MAX-EXECUTION-TIME": "Max job duration", "MAX-EXECUTION-TIME-MINUTES": "Minutes", + "MAX-EXECUTION-TIME-HOURS": "Hours", "MAX-EXECUTION-TIME-HINT": "0 Minute means unlimited duration" }, "SCHEDULE": "Schedule", diff --git a/src/assets/i18n/it.json b/src/assets/i18n/it.json index 6da9430..20777c4 100644 --- a/src/assets/i18n/it.json +++ b/src/assets/i18n/it.json @@ -48,6 +48,7 @@ "SELECT-FILES-DIRS": "File e cartelle selezionate", "MAX-EXECUTION-TIME": "Durata massima del lavoro", "MAX-EXECUTION-TIME-MINUTES": "Minuti", + "MAX-EXECUTION-TIME-HOURS": "Ore", "MAX-EXECUTION-TIME-HINT": "0 Minuti vuol dire durata illimitata" }, "SCHEDULE": "Programmazione", From 9210f7fec044cb33bacc469239201c651fdc5e26 Mon Sep 17 00:00:00 2001 From: Umberto Russo Date: Mon, 11 Mar 2019 13:53:32 +0100 Subject: [PATCH 5/9] Added --no-follow-symlinks option to aws sync command --- src/app/providers/aws.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/providers/aws.service.ts b/src/app/providers/aws.service.ts index 3889d6f..709d934 100644 --- a/src/app/providers/aws.service.ts +++ b/src/app/providers/aws.service.ts @@ -130,6 +130,7 @@ export class AwsService { } s3Args.push('--no-progress'); + s3Args.push('--no-follow-symlinks'); commands.push(s3Args); } From c76003a797b814a10ac47d5475a3a6179f3bf0f0 Mon Sep 17 00:00:00 2001 From: Umberto Russo Date: Tue, 12 Mar 2019 11:54:16 +0100 Subject: [PATCH 6/9] Changed email errors notification - now the errors email is sent only on job done. --- src/app/providers/aws.service.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/app/providers/aws.service.ts b/src/app/providers/aws.service.ts index 709d934..77a9972 100644 --- a/src/app/providers/aws.service.ts +++ b/src/app/providers/aws.service.ts @@ -160,8 +160,6 @@ export class AwsService { job.setAlert(true); this.jobService.save(job); this.logService.printLog(LogType.ERROR, 'Can\'t run job ' + job.name + ' because of: \r\n' + err); - this.notification.sendNotification('Problem with job: ' + job.name, 'The job ' + job.name + - ' has just stopped because of ' + err + '.
- AWS S3 Backup', 'email', true); if (err) { return callback(err); } @@ -178,8 +176,6 @@ export class AwsService { job.setAlert(true); this.jobService.save(job); this.logService.printLog(LogType.ERROR, 'Error with job ' + job.name + ' because of: \r\n' + err); - this.notification.sendNotification('Problem with job: ' + job.name, 'The job ' + job.name + - ' has just throw an error because of ' + err + '.
- AWS S3 Backup', 'email', true); }); } else { @@ -209,6 +205,12 @@ export class AwsService { if (job.type !== JobType.Live) { this.logService.printLog(LogType.INFO, 'End job: ' + job.name); + + if (job.alert) { + this.notification.sendNotification('Problem with job: ' + job.name, 'The job ' + job.name + + ' generated an alert, for further details see the log in attachment.
- AWS S3 Backup', 'email', true); + } + this.notification.sendNotification('End job: ' + job.name, 'The job ' + job.name + ' has just ended.
- AWS S3 Backup', 'email'); this.jobService.checkExpiredJob(job); From 8cd6aa762aee8dee642778e3014199ae4a3f212e Mon Sep 17 00:00:00 2001 From: Umberto Russo Date: Tue, 12 Mar 2019 12:30:48 +0100 Subject: [PATCH 7/9] Added translation (IT) for the next run date in the job list --- src/app/components/jobs-list/jobs-list.component.html | 3 ++- src/app/providers/job-scheduler.service.ts | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/app/components/jobs-list/jobs-list.component.html b/src/app/components/jobs-list/jobs-list.component.html index 73dce6d..c83a94f 100644 --- a/src/app/components/jobs-list/jobs-list.component.html +++ b/src/app/components/jobs-list/jobs-list.component.html @@ -24,7 +24,8 @@

{{job.name}}

{{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-MINUTES' | translate}} = {{maxExecutionTimeHours[jobIndex]}} {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-HOURS' | translate}}
- - {{ 'PAGES.JOB-LIST.NEXT-RUN' | translate }}: {{scheduledJobs[job.id]}} +
+ {{ 'PAGES.JOB-LIST.NEXT-RUN' | translate }}: {{scheduledJobs[job.id]}} {{ 'PAGES.JOB-LIST.NO-NEXT-RUN' | translate }}

diff --git a/src/app/providers/job-scheduler.service.ts b/src/app/providers/job-scheduler.service.ts index 9150a03..4ebf440 100644 --- a/src/app/providers/job-scheduler.service.ts +++ b/src/app/providers/job-scheduler.service.ts @@ -11,6 +11,7 @@ import {AwsService} from './aws.service'; import * as chokidar from 'chokidar'; import {LogService} from './log.service'; import {LogType} from '../enum/log.type.enum'; +import {TranslateService} from '@ngx-translate/core'; @Injectable({ providedIn: 'root' @@ -23,7 +24,8 @@ export class JobSchedulerService { private jobService: JobsService, private cronService: CronService, private awsService: AwsService, - private logService: LogService + private logService: LogService, + private translate: TranslateService, ) { this.scheduledJobs = []; } @@ -171,6 +173,7 @@ export class JobSchedulerService { getScheduledJobsFormattedTime(): Array { const res = []; + moment.locale(this.translate.currentLang); this.scheduledJobs.forEach((scheduledJob) => { if (scheduledJob.scheduler instanceof schedule.Job && scheduledJob.scheduler.nextInvocation() !== null) { res[scheduledJob.jobId] = (moment(scheduledJob.scheduler.nextInvocation().toISOString()).format('LLLL')); From e153360dd6406ab76730511cc9940703d58c87aa Mon Sep 17 00:00:00 2001 From: Umberto Russo Date: Tue, 12 Mar 2019 16:46:00 +0100 Subject: [PATCH 8/9] Fixed backup is running loader and AWS CLI S3 exit code 2 - The backup 'is running' spinner remain stuck when the AWS CLI S3 generates an error - The backup don't continue if the previous file/folder generate an error with an exit code 2 of AWS CLI --- src/app/providers/aws.service.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/providers/aws.service.ts b/src/app/providers/aws.service.ts index 77a9972..d560512 100644 --- a/src/app/providers/aws.service.ts +++ b/src/app/providers/aws.service.ts @@ -149,7 +149,7 @@ export class AwsService { proc.on('close', (code) => { this.processedHandler.killJobProcess(job.id, proc.pid); - if (code === 0) { + if (code === 0 || code === 2) { next(); } else { return callback(null, null); @@ -191,6 +191,7 @@ export class AwsService { let timeout = null; if ( job.maxExecutionTime > 0 ) { timeout = setTimeout(() => { + this.logService.printLog(LogType.INFO, 'The job ' + job.name + ' has just stopped because hit the maximum execution time. \r\n'); this.processedHandler.killJobProcesses(job.id); }, job.maxExecutionTime); } @@ -202,6 +203,7 @@ export class AwsService { } job.setIsRunning(false); + this.jobService.save(job); if (job.type !== JobType.Live) { this.logService.printLog(LogType.INFO, 'End job: ' + job.name); From 07d07c46d0f9dffe19bcb15d8833f053227f3a4a Mon Sep 17 00:00:00 2001 From: Umberto Russo Date: Tue, 12 Mar 2019 16:59:09 +0100 Subject: [PATCH 9/9] Changed app version and changelog --- CHANGELOG.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0544e5f..ab96430 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,19 @@ ### Changelog All notable changes to this project will be documented in this file. +## [1.5.0] - 2019-03-12 +### Fixed +- The backup 'is running' spinner remain stuck when the AWS CLI S3 generates an error +- The backup don't continue if the previous file/folder generate an error with an exit code 2 of the AWS CLI +### Added +- Auto start on OS boot +- App single instance check to avoid multiple app instances +- Time (minutes to hours ) and data (KB/s to Mb/s) unit conversion in settings and add/edit job pages +- --no-follow-symlinks option to aws s3 sync command +- Italian translation for the next run date in the job list +### Changed +- Email errors notification, now you will receive error log only when the job is done + ## [1.4.1] - 2019-03-07 ### Fixed - Email notification: logs attachment was missing on backup error diff --git a/package.json b/package.json index b253d87..d870522 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aws-s3-backup", - "version": "1.4.1", + "version": "1.5.0", "description": "AWS S3 backup system", "homepage": "https://github.com/ulver2812/aws-s3-backup", "author": {