Skip to content

Commit

Permalink
Merge branch 'milestone-1.5.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
ulver2812 committed Mar 12, 2019
2 parents fb3536e + 07d07c4 commit 3acadac
Show file tree
Hide file tree
Showing 18 changed files with 147 additions and 27 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
16 changes: 7 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
<p align="center">
<img src="https://raw.githubusercontent.com/ulver2812/aws-s3-backup/master/aws-s3-backup-icon.png" alt="AWS S3 Backup"/>
<img src="https://raw.githubusercontent.com/ulver2812/aws-s3-backup/master/aws-s3-backup-icon.png" alt="AWS S3 Backup"/><br/>
Backup on AWS S3 ? Never been so easy!
</p>

[![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)]()
<p align="center">
<a href="#"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square" alt="PR"></a>
<a href="#"><img src="http://img.shields.io/badge/Licence-MIT-brightgreen.svg" alt="MIT"></a>
<a href="#"><img src="https://img.shields.io/badge/tested%20on-Win%2010%20x64-brightgreen.svg" alt="Tested on Win 10"></a>
</p>

# Introduction

Expand Down Expand Up @@ -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
38 changes: 38 additions & 0 deletions main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,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() {
Expand Down Expand Up @@ -79,6 +80,7 @@ function createWindow() {

win.on('close', (event) => {
win.hide();
winIsHidden = true;
event.preventDefault();
});
}
Expand All @@ -100,6 +102,7 @@ function createTray() {
tray.setContextMenu(contextMenu);
tray.on('click', () => {
win.show();
winIsHidden = false;
});
}

Expand All @@ -121,10 +124,45 @@ 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')
});
}

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.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down
4 changes: 2 additions & 2 deletions src/app/components/edit-job/edit-job.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,10 @@ <h3 class="mat-error">{{ 'PAGES.EDIT-JOB.FIELDS.SCHEDULE-ERR' | translate }}</h3
[disabled]="jobTypeSelected !== jobType.Recurring">
</mat-form-field>
<mat-form-field>
<input [(ngModel)]="jobMaxExecutionTime" [required]="jobTypeSelected !== jobType.Live" name="jobMaxExecutionTime" matInput
<input [(ngModel)]="jobMaxExecutionTime" (ngModelChange)="convertMinutesToHours($event)" [required]="jobTypeSelected !== jobType.Live" name="jobMaxExecutionTime" matInput
placeholder="{{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME' | translate}}" type="number" min="0" step="1"
[disabled]="jobTypeSelected === jobType.Live">
<span matSuffix>{{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-MINUTES' | translate}}</span>
<span matSuffix>{{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-MINUTES' | translate}} = {{maxExecutionHours}} {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-HOURS' | translate}}</span>
<mat-hint>{{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-HINT' | translate}}</mat-hint>
</mat-form-field>
</mat-card>
Expand Down
7 changes: 7 additions & 0 deletions src/app/components/edit-job/edit-job.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(() => {
Expand Down Expand Up @@ -195,4 +198,8 @@ export class EditJobComponent implements OnInit {
}
}

convertMinutesToHours(minutes) {
const res = minutes / 60;
this.maxExecutionHours = res.toFixed(2);
}
}
7 changes: 4 additions & 3 deletions src/app/components/jobs-list/jobs-list.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ <h2>{{ 'PAGES.JOB-LIST.TITLE' | translate }}</h2>
<mat-divider [inset]="true"></mat-divider>
<br>
<mat-list *ngIf="jobs.length > 0">
<mat-list-item class="job-item" *ngFor="let job of jobs" [routerLink]="['edit-job', job.id]">
<mat-list-item class="job-item" *ngFor="let job of jobs; let jobIndex = index" [routerLink]="['edit-job', job.id]">
<mat-icon svgIcon="custom_icon_alert" matTooltip="{{ 'PAGES.JOB-LIST.ALERT' | translate }}" *ngIf="job.alert" mat-list-icon></mat-icon>
<mat-icon svgIcon="custom_icon_check" matTooltip="{{ 'PAGES.JOB-LIST.NO-ALERT' | translate }}" *ngIf="!job.alert" mat-list-icon></mat-icon>
<mat-icon svgIcon="custom_icon_working" matTooltip="{{ 'PAGES.JOB-LIST.ACTIVE' | translate }}" *ngIf="job.status === jobStatus.Active" mat-list-icon></mat-icon>
Expand All @@ -21,10 +21,11 @@ <h4 mat-line>{{job.name}}</h4>
</span>
<span *ngIf="job.type !== jobType.Live && job.maxExecutionTime !== 0">
- <strong>{{ 'PAGES.JOB-LIST.MAX-EXECUTION-TIME' | translate }}:</strong> {{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}}
</span>
<span *ngIf="job.type !== jobType.OneTime && job.status !== jobStatus.Terminated">
- <strong>{{ 'PAGES.JOB-LIST.NEXT-RUN' | translate }}: </strong> <span *ngIf="scheduledJobs[job.id]; else no_next_run">{{scheduledJobs[job.id]}}</span>
<br/>
<strong>{{ 'PAGES.JOB-LIST.NEXT-RUN' | translate }}: </strong> <span *ngIf="scheduledJobs[job.id]; else no_next_run">{{scheduledJobs[job.id]}}</span>
<ng-template #no_next_run> {{ 'PAGES.JOB-LIST.NO-NEXT-RUN' | translate }}</ng-template>
</span>
</p>
Expand Down
5 changes: 5 additions & 0 deletions src/app/components/jobs-list/jobs-list.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class JobsListComponent implements OnInit {
jobType = JobType;
jobs: Job[];
scheduledJobs: string[];
maxExecutionTimeHours: string[];

constructor(
private jobService: JobsService,
Expand All @@ -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();
}

Expand Down
4 changes: 2 additions & 2 deletions src/app/components/new-job/new-job.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ <h3 class="mat-error">{{ 'PAGES.EDIT-JOB.FIELDS.SCHEDULE-ERR' | translate }}</h3
<mat-form-field>
<input [(ngModel)]="jobMaxExecutionTimeFormatted" [required]="job.type !== jobType.Live" name="jobMaxExecutionTime" matInput
placeholder="{{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME' | translate}}" type="number" min="0" step="1"
[disabled]="job.type === jobType.Live" (ngModelChange)="job.setMaxExecutionTime($event)">
<span matSuffix>{{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-MINUTES' | translate}}</span>
[disabled]="job.type === jobType.Live" (ngModelChange)="convertMinutesToHours($event)" (ngModelChange)="job.setMaxExecutionTime($event)">
<span matSuffix>{{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-MINUTES' | translate}} = {{maxExecutionHours}} {{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-HOURS' | translate}}</span>
<mat-hint>{{'PAGES.EDIT-JOB.FIELDS.MAX-EXECUTION-TIME-HINT' | translate}}</mat-hint>
</mat-form-field>
</mat-card>
Expand Down
7 changes: 7 additions & 0 deletions src/app/components/new-job/new-job.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export class NewJobComponent implements OnInit {
jobDay = [];
jobDayOfMonth = [];
jobTime = '00:00';
maxExecutionHours: string;

months = this.cronService.months;
days = this.cronService.days;
Expand All @@ -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() {
Expand Down Expand Up @@ -112,4 +114,9 @@ export class NewJobComponent implements OnInit {
}
return false;
}

convertMinutesToHours(minutes) {
const res = minutes / 60;
this.maxExecutionHours = res.toFixed(2);
}
}
17 changes: 15 additions & 2 deletions src/app/components/settings/settings.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ <h2>{{'PAGES.S3-SETTINGS.TITLE' | translate}}</h2>
</mat-form-field>
<p></p>
<mat-form-field>
<input [(ngModel)]="settings.s3MaxBandwidth " matInput type="number" min="0" placeholder="{{'PAGES.S3-SETTINGS.MAX-BANDWIDTH' | translate}}">
<span matSuffix>KB/s&nbsp;</span>
<input [(ngModel)]="settings.s3MaxBandwidth" (ngModelChange)="convertS3MaxBandwidth($event)" matInput type="number" min="0" placeholder="{{'PAGES.S3-SETTINGS.MAX-BANDWIDTH' | translate}}">
<span matSuffix>KB/s = {{bandwidthMbs}}</span>
<mat-hint>{{'PAGES.S3-SETTINGS.MAX-BANDWIDTH-DESC' | translate}}</mat-hint>
</mat-form-field>
</mat-card>
Expand Down Expand Up @@ -107,4 +107,17 @@ <h2>{{'PAGES.NOTIFICATIONS-SETTINGS.TITLE' | translate}}</h2>
</div>
</div>

<div class="flex-container" fxLayout fxLayoutGap="40px">
<div class="flex-element" fxFlex>
<mat-card>
<section class="mat-typography">
<h2>{{'PAGES.APP-SETTINGS.TITLE' | translate}}</h2>
</section>
<p>
<mat-checkbox [(ngModel)]="settings.autoStart"> {{ 'PAGES.APP-SETTINGS.AUTOSTART' | translate }}</mat-checkbox>
</p>
</mat-card>
</div>
</div>

<button mat-raised-button class="float-right" color="primary" (click)="save()">{{'PAGES.SETTINGS.SAVE' | translate}}</button>
17 changes: 15 additions & 2 deletions src/app/components/settings/settings.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -37,13 +38,16 @@ export class SettingsComponent implements OnInit {
emailSender: string,
emailReceivers: string[],
s3MaxConcurrentRequests: number,
s3MaxBandwidth: number
s3MaxBandwidth: number,
autoStart: boolean
};

awsCliStatus: any;
awsCliCredentials: any;
spinner = true;

bandwidthMbs: string;

regions = [
{id: 'eu-west-1', value: 'EU (Ireland)'},
{id: 'eu-west-2', value: 'EU (London)'},
Expand Down Expand Up @@ -74,7 +78,8 @@ export class SettingsComponent implements OnInit {
private appMenuService: AppMenuService,
private aws: AwsService,
private utilsService: UtilsService,
private translate: TranslateService
private translate: TranslateService,
private electronService: ElectronService
) {
}

Expand All @@ -96,11 +101,14 @@ export class SettingsComponent implements OnInit {

this.checkSettings();
this.utilsService.checkInternetConnection();

this.convertS3MaxBandwidth(this.settings.s3MaxBandwidth);
}

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',
Expand Down Expand Up @@ -148,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';
}
}
2 changes: 2 additions & 0 deletions src/app/interfaces/ijob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,7 @@ export interface IJob {

getMaxExecutionTimeFormatted(): number;

getMaxExecutionTimeFormattedHours(): string;

setMaxExecutionTime(formattedMaxExecutionTime);
}
5 changes: 5 additions & 0 deletions src/app/models/job.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Loading

0 comments on commit 3acadac

Please sign in to comment.