Skip to content

Commit e1cdde8

Browse files
Merge pull request #283 from frg-fossee/develop
Merge develop into master
2 parents f6da5c0 + 31bd988 commit e1cdde8

File tree

103 files changed

+3755
-869
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+3755
-869
lines changed

ArduinoFrontend/src/app/Libs/Workspace.ts

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,8 +477,8 @@ export class Workspace {
477477
if (window.isCodeEditorOpened) {
478478
return;
479479
}
480-
// console.log([event.ctrlKey, event.key]);
481-
if (event.key === 'Delete' || event.key === 'Backspace') {
480+
if ((event.key === 'Delete' || event.key === 'Backspace')
481+
&& !(event['target']['localName'] === 'input' || event['target']['localName'] === 'textarea')) {
482482
// Backspace or Delete
483483
Workspace.DeleteComponent();
484484
}
@@ -1050,4 +1050,76 @@ export class Workspace {
10501050
// Hide Loading animation
10511051
window.hideLoading();
10521052
}
1053+
1054+
1055+
/**
1056+
* Function generates a JSON object containing all details of the workspace and downloads it
1057+
* @param name string
1058+
* @param description string
1059+
*/
1060+
static SaveJson(name: string = '', description: string = '') {
1061+
1062+
const id = Date.now();
1063+
1064+
// Default Save object
1065+
const saveObj = {
1066+
id,
1067+
canvas: {
1068+
x: Workspace.translateX,
1069+
y: Workspace.translateY,
1070+
scale: Workspace.scale
1071+
},
1072+
project: {
1073+
name,
1074+
description,
1075+
created_at: Date.now(),
1076+
}
1077+
};
1078+
1079+
// For each item in the scope
1080+
for (const key in window.scope) {
1081+
// if atleast one component is present
1082+
if (window.scope[key] && window.scope[key].length > 0) {
1083+
saveObj[key] = [];
1084+
// Add the component to the save object
1085+
for (const item of window.scope[key]) {
1086+
if (item.save) {
1087+
saveObj[key].push(item.save());
1088+
}
1089+
}
1090+
}
1091+
}
1092+
1093+
// Export JSON File & Download it
1094+
const filename = `${name}.json`;
1095+
const jsonStr = JSON.stringify(saveObj);
1096+
1097+
const element = document.createElement('a');
1098+
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(jsonStr));
1099+
element.setAttribute('download', filename);
1100+
1101+
element.style.display = 'none';
1102+
document.body.appendChild(element);
1103+
1104+
element.click();
1105+
1106+
document.body.removeChild(element);
1107+
1108+
return true;
1109+
1110+
}
1111+
1112+
/**
1113+
* Function to return if workspace is empty or not
1114+
* @returns 'False' if workspace is not empty & 'True' if workspace is empty
1115+
*/
1116+
static checkIfWorkspaceEmpty() {
1117+
for (const key in window.scope) {
1118+
if (window.scope[key].length > 0) {
1119+
return false;
1120+
}
1121+
}
1122+
return true;
1123+
}
1124+
10531125
}

ArduinoFrontend/src/app/app.module.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ import { HeaderComponent } from './header/header.component';
3535
import { ViewProjectComponent } from './view-project/view-project.component';
3636
import { AlertModalComponent } from './alert/alert-modal/alert-modal.component';
3737
import { ConfirmModalComponent } from './alert/confirm-modal/confirm-modal.component';
38+
import { ExportJSONDialogComponent } from './export-jsondialog/export-jsondialog.component';
39+
import { ExitConfirmDialogComponent } from './exit-confirm-dialog/exit-confirm-dialog.component';
3840

3941
/**
4042
* Monaco OnLoad Function
@@ -67,6 +69,8 @@ const monacoConfig: NgxMonacoEditorConfig = {
6769
HeaderComponent,
6870
AlertModalComponent,
6971
ConfirmModalComponent,
72+
ExportJSONDialogComponent,
73+
ExitConfirmDialogComponent,
7074
],
7175
imports: [
7276
BrowserModule,
@@ -89,7 +93,15 @@ const monacoConfig: NgxMonacoEditorConfig = {
8993
// providers: [{provide: LocationStrategy, useClass: PathLocationStrategy}],
9094
providers: [{ provide: LocationStrategy, useClass: HashLocationStrategy }],
9195
bootstrap: [AppComponent],
92-
entryComponents: [ViewComponentInfoComponent, ExportfileComponent, ComponentlistComponent, AlertModalComponent, ConfirmModalComponent],
96+
entryComponents: [
97+
ViewComponentInfoComponent,
98+
ExportfileComponent,
99+
ComponentlistComponent,
100+
AlertModalComponent,
101+
ConfirmModalComponent,
102+
ExportJSONDialogComponent,
103+
ExitConfirmDialogComponent,
104+
],
93105
schemas: [
94106
CUSTOM_ELEMENTS_SCHEMA
95107
],
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.action-div{
2+
display: flex;
3+
justify-content: space-around;
4+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<h2 mat-dialog-title>Do you want to exit?</h2>
2+
<div mat-dialog-actions class="action-div">
3+
<button mat-raised-button color="warn" (click)="yesClick()">Yes</button>
4+
<button mat-raised-button color="primary" mat-dialog-close>No</button>
5+
</div>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { MatDialogModule, MatDialogRef } from '@angular/material';
3+
4+
import { ExitConfirmDialogComponent } from './exit-confirm-dialog.component';
5+
6+
describe('ExitConfirmDialogComponent', () => {
7+
let component: ExitConfirmDialogComponent;
8+
let fixture: ComponentFixture<ExitConfirmDialogComponent>;
9+
10+
beforeEach(async(() => {
11+
TestBed.configureTestingModule({
12+
imports: [MatDialogModule],
13+
declarations: [ExitConfirmDialogComponent],
14+
providers: [
15+
{ provide: MatDialogRef, useValue: {} },
16+
]
17+
})
18+
.compileComponents();
19+
}));
20+
21+
beforeEach(() => {
22+
fixture = TestBed.createComponent(ExitConfirmDialogComponent);
23+
component = fixture.componentInstance;
24+
fixture.detectChanges();
25+
});
26+
27+
it('should create', () => {
28+
expect(component).toBeTruthy();
29+
});
30+
});
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Component, OnInit } from '@angular/core';
2+
import { MatDialogRef } from '@angular/material';
3+
4+
@Component({
5+
selector: 'app-exit-confirm-dialog',
6+
templateUrl: './exit-confirm-dialog.component.html',
7+
styleUrls: ['./exit-confirm-dialog.component.css']
8+
})
9+
export class ExitConfirmDialogComponent implements OnInit {
10+
11+
constructor(public dialogRef: MatDialogRef<ExitConfirmDialogComponent>) { }
12+
13+
ngOnInit() {
14+
}
15+
16+
// Function to handle if user want to exit
17+
yesClick() {
18+
this.dialogRef.close(true);
19+
}
20+
21+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.full-width{
2+
width: 100%;
3+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<div mat-dialog-title>
2+
Enter the name of File to be Saved
3+
</div>
4+
<mat-dialog-content>
5+
<br>
6+
<mat-form-field class="full-width">
7+
<mat-label>File Name</mat-label>
8+
<input matInput [(ngModel)]="fileName">
9+
</mat-form-field>
10+
11+
</mat-dialog-content>
12+
<mat-dialog-actions>
13+
14+
<button mat-raised-button (click)="saveProject()" color="primary">Download Project</button>
15+
<button mat-raised-button mat-dialog-close color="warn">Close</button>
16+
17+
</mat-dialog-actions>
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
2+
import { FormsModule } from '@angular/forms';
3+
import { MatDialogModule, MatDialogRef, MatFormFieldModule, MAT_DIALOG_DATA } from '@angular/material';
4+
import { RouterTestingModule } from '@angular/router/testing';
5+
import { Workspace } from '../Libs/Workspace';
6+
import { ExportJSONDialogComponent } from './export-jsondialog.component';
7+
8+
describe('ExportJSONDialogComponent', () => {
9+
10+
let component: ExportJSONDialogComponent;
11+
let fixture: ComponentFixture<ExportJSONDialogComponent>;
12+
13+
beforeEach(async () => {
14+
TestBed.configureTestingModule({
15+
imports: [
16+
RouterTestingModule,
17+
MatFormFieldModule,
18+
FormsModule,
19+
MatDialogModule,
20+
],
21+
declarations: [
22+
ExportJSONDialogComponent
23+
],
24+
providers: [
25+
{ provide: MatDialogRef, useValue: {} },
26+
{ provide: MAT_DIALOG_DATA, useValue: { description: 'this is a desc', title: 'title' } },
27+
]
28+
}).compileComponents();
29+
});
30+
31+
beforeEach(() => {
32+
fixture = TestBed.createComponent(ExportJSONDialogComponent);
33+
component = fixture.componentInstance;
34+
});
35+
36+
it('should create the app', () => {
37+
expect(component).toBeTruthy();
38+
});
39+
40+
it('Value of fileName variable should be given string', () => {
41+
expect(component.fileName).toBe('title');
42+
});
43+
44+
it('Value of Description variable should be given string', () => {
45+
expect(component.description).toBe('this is a desc');
46+
});
47+
48+
it('should return truthy as workspace is empty', () => {
49+
expect(Workspace.checkIfWorkspaceEmpty()).toBeTruthy();
50+
});
51+
52+
it('should return falsey as workspace is not empty', () => {
53+
component.ngOnInit();
54+
window['scope'] = {
55+
id: 1620892078891,
56+
canvas: { x: 0, y: 0, scale: 1 },
57+
project: {
58+
name: 'Untitled',
59+
description: '',
60+
created_at: 1620892078891
61+
},
62+
Resistor: [{ x: 483, y: 209, tx: 68, ty: 100, id: 1620892071196, data: { value: 1000, tolerance: 10 } }]
63+
};
64+
expect(Workspace.checkIfWorkspaceEmpty()).toBeFalsy();
65+
});
66+
67+
it('should return truthy after downloading json file', () => {
68+
expect(Workspace.SaveJson()).toBeTruthy();
69+
});
70+
});
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Component, Inject, OnInit } from '@angular/core';
2+
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
3+
import { Workspace } from '../Libs/Workspace';
4+
5+
@Component({
6+
selector: 'app-export-jsondialog',
7+
templateUrl: './export-jsondialog.component.html',
8+
styleUrls: ['./export-jsondialog.component.css']
9+
})
10+
export class ExportJSONDialogComponent implements OnInit {
11+
12+
description: string;
13+
fileName = '';
14+
15+
constructor(
16+
public dialogRef: MatDialogRef<ExportJSONDialogComponent>,
17+
@Inject(MAT_DIALOG_DATA) public data) {
18+
this.description = data.description;
19+
this.fileName = data.title;
20+
}
21+
22+
ngOnInit() {
23+
}
24+
25+
/**
26+
* Save Project function, Calls Workspace.SaveJson with edited fileName and then closes project
27+
*/
28+
saveProject() {
29+
Workspace.SaveJson(this.fileName, this.description);
30+
this.dialogRef.close();
31+
}
32+
33+
}

ArduinoFrontend/src/app/header/header.component.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
<!--<div style="flex-basis: 200px; line-height: 60px; text-align: right; padding-right: 10px;font-size: 18px;">Gallery
1313
</div>-->
1414
<div style="display: flex; padding: 10px;" *ngIf="!username">
15+
<a mat-stroked-button [href]="window.location.protocol + '//' + window.location.hostname" style="margin-right: 10px;">Home</a>
16+
<a mat-stroked-button [routerLink]="['/dashboard']" style="margin-right: 10px;">Dashboard</a>
1517
<a mat-stroked-button [routerLink]="['/gallery']" style="margin-right: 10px;">Gallery</a>
18+
<a mat-stroked-button [routerLink]="['/simulator']" style="margin-right: 10px">Editor</a>
1619
<a mat-stroked-button (click)="Login()">Login</a>
1720
</div>
1821
<div class="dropdown my-dropdown" *ngIf="username">

ArduinoFrontend/src/app/header/header.component.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ export class HeaderComponent implements OnInit {
1919
* Username
2020
*/
2121
username: string;
22+
/**
23+
* window
24+
*/
25+
window: any;
2226
/**
2327
* Header Title
2428
*/
@@ -55,7 +59,8 @@ export class HeaderComponent implements OnInit {
5559
// }
5660
});
5761
}
58-
62+
// Initializing window
63+
this.window = window;
5964
}
6065
/**
6166
* Redirect to login

ArduinoFrontend/src/app/simulator/simulator.component.html

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!-- As a heading -->
22
<nav class="navbar navbar-expand-lg navbar-light text-white" style="background-color: whitesmoke;height: 50px;">
3-
<a [routerLink]="['/']">
3+
<a (click)="exitProject()">
44
<img src="./assets/icon.png" style="height: 40px;display: none;margin-top:10px;margin-right: 1em;"
55
class="d-md-block" alt="AOC">
66
</a>
@@ -46,7 +46,10 @@
4646
</ul>
4747

4848
<div class="navbar-nav ml-auto" *ngIf="!token">
49+
<a mat-raised-button [href]="window.location.protocol + '//' + window.location.hostname" style="margin-right: 10px;">Home</a>
4950
<a mat-raised-button [routerLink]="['/dashboard']" style="margin-right: 10px;">Dashboard</a>
51+
<a mat-raised-button [routerLink]="['/gallery']" style="margin-right: 10px;">Gallery</a>
52+
<a mat-raised-button [routerLink]="['/simulator']" style="margin-right: 10px;">Editor</a>
5053
<a mat-raised-button (click)="Login()">Login</a>
5154
</div>
5255

@@ -135,7 +138,21 @@
135138
</div>
136139
<!--/simulation loading svg-->
137140

141+
<!-- Import export -->
138142
<span class="pipe">|</span>
143+
<button mat-icon-button matTooltip="Download JSON file" (click)="exportJson()" id="importBtn"
144+
style="align-items: center;background: transparent; margin: auto;" class="mt-1">
145+
<i style="font-size: 20px;color: black;" class="fa fa-download" id="download_icon"></i>
146+
</button>
147+
148+
<button mat-icon-button matTooltip="Import JSON file"
149+
style="align-items: center;background: transparent; margin: auto;" class="mt-1">
150+
<label style="font-size: 20px;color: black; cursor: pointer; width: 100%;" class="fa fa-upload">
151+
<input type="file" style="display: none;" #jsonFile id="jsonFile" (change)="importJson(jsonFile.files[0])">
152+
</label>
153+
</button>
154+
<span class="pipe">|</span>
155+
<!-- Import export -->
139156

140157
<a href="../#/simulator" target="_blank">
141158
<button mat-icon-button matTooltip="New Project" style="align-items: center;background: transparent;" class="mt-1">

0 commit comments

Comments
 (0)