aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTAMARA JERINIC <tamara.jerinic@gmail.com>2022-05-25 20:00:03 +0200
committerTAMARA JERINIC <tamara.jerinic@gmail.com>2022-05-25 20:00:03 +0200
commit8d96241a6958a5797d7bf203fbfb2bfe2a4ec391 (patch)
tree373ab9b113ecbe20bf6fad30ad4a7a860e3f4a69
parent7dc17a7b94984d24829b6e30ee575e493f2ab787 (diff)
parent54a1eaf3b2176a41dcd2677eb64843638852c371 (diff)
Merge branch 'redesign' of http://gitlab.pmf.kg.ac.rs/igrannonica/neuronstellar into redesign
-rw-r--r--backend/api/api/.config/dotnet-tools.json12
-rw-r--r--frontend/src/app/_elements/column-table/column-table.component.ts16
-rw-r--r--frontend/src/app/_elements/folder/folder.component.css11
-rw-r--r--frontend/src/app/_elements/folder/folder.component.html27
-rw-r--r--frontend/src/app/_elements/folder/folder.component.ts30
-rw-r--r--frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.css21
-rw-r--r--frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.html24
-rw-r--r--frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.spec.ts25
-rw-r--r--frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.ts68
-rw-r--r--frontend/src/app/app.module.ts4
10 files changed, 219 insertions, 19 deletions
diff --git a/backend/api/api/.config/dotnet-tools.json b/backend/api/api/.config/dotnet-tools.json
new file mode 100644
index 00000000..e80b80ff
--- /dev/null
+++ b/backend/api/api/.config/dotnet-tools.json
@@ -0,0 +1,12 @@
+{
+ "version": 1,
+ "isRoot": true,
+ "tools": {
+ "dotnet-ef": {
+ "version": "6.0.5",
+ "commands": [
+ "dotnet-ef"
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/frontend/src/app/_elements/column-table/column-table.component.ts b/frontend/src/app/_elements/column-table/column-table.component.ts
index 4b10401d..8398f7ef 100644
--- a/frontend/src/app/_elements/column-table/column-table.component.ts
+++ b/frontend/src/app/_elements/column-table/column-table.component.ts
@@ -15,6 +15,7 @@ import Shared from 'src/app/Shared';
import { PieChartComponent } from '../_charts/pie-chart/pie-chart.component';
import { BoxPlotComponent } from '../_charts/box-plot/box-plot.component';
import { ActivatedRoute } from '@angular/router';
+import { UpdateExperimentDialogComponent } from 'src/app/_modals/update-experiment-dialog/update-experiment-dialog.component';
@Component({
selector: 'app-column-table',
@@ -365,11 +366,20 @@ export class ColumnTableComponent implements AfterViewInit {
}
openUpdateExperimentDialog() {
- this.experimentService.updateExperiment(this.experiment).subscribe((response) => {
- Object.assign(this.experiment, response);
+ const dialogRef = this.dialog.open(UpdateExperimentDialogComponent, {
+ width: '350px',
+ data: { experiment: this.experiment }
+ });
+ dialogRef.afterClosed().subscribe(experiment => {
+ if (experiment == undefined)
+ return;
+ if (this.experiment._id != experiment._id)
+ Shared.openDialog("Novi eksperiment", "Uspešno ste sačuvali novi eksperiment. Nastavite rad na njemu.");
+ else
+ Shared.openDialog("Izmena eksperimenta", "Uspešno ste izmenili podatke o eksperimentu.");
+ Object.assign(this.experiment, experiment);
this.experiment._columnsSelected = true;
this.experimentChanged.emit();
- Shared.openDialog("Izmena eksperimenta", "Uspešno ste izmenili podatke o eksperimentu.");
});
}
diff --git a/frontend/src/app/_elements/folder/folder.component.css b/frontend/src/app/_elements/folder/folder.component.css
index 682fc645..810ad05d 100644
--- a/frontend/src/app/_elements/folder/folder.component.css
+++ b/frontend/src/app/_elements/folder/folder.component.css
@@ -184,9 +184,13 @@
}
.file-bottom-buttons {
- position: absolute;
- bottom: 5px;
- right: 4%;
+ position: relative;
+ position: relative;
+ top:-36px
+
+}
+.file-bottom-buttons-helper{
+ position: relative;
display: flex;
flex-direction: row-reverse;
}
@@ -196,6 +200,7 @@
color: var(--offwhite);
border-radius: 4px;
border: 1px solid var(--ns-primary);
+ background-color: var(--ns-bg-dark-50);
margin: 5px;
padding: 5px;
cursor: pointer;
diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html
index 52f19753..afb6085d 100644
--- a/frontend/src/app/_elements/folder/folder.component.html
+++ b/frontend/src/app/_elements/folder/folder.component.html
@@ -58,17 +58,6 @@
<!--{{fileToDisplay ? fileToDisplay.name : 'No file selected.'}} {{selectedFileIndex}} {{hoveringOverFileIndex}}-->
<div class="folder-inside bg-blur">
<div class="file-content" [ngClass]="{'form-hidden' : listView}">
- <div class="file-bottom-buttons" *ngIf="selectedTab != TabType.NewFile">
- <button *ngIf="this.selectedFile && selectedTab == TabType.File && privacy != Privacy.Public" class="btn-clear file-button" (click)="deleteFile(this.selectedFile, $event)">
- <mat-icon matTooltip="Obriši" matTooltipPosition="right">delete</mat-icon>
- </button>
- <button *ngIf="this.selectedFile && selectedTab==TabType.File && FolderType.Dataset==this.type" class="btn-clear file-button" (click)="downloadFile(this.selectedFile,$event)" style="display: inline-block;">
- <mat-icon matTooltip="Preuzmi" matTooltipPosition="before">download</mat-icon>
- </button>
- <!-- <button class="btn-clear file-button">
- <mat-icon>zoom_out_map</mat-icon>
- </button> -->
- </div>
<app-form-model [ngClass]="{'form-hidden': type != FolderType.Model}" [forExperiment]="forExperiment" [hideProblemType]="(forExperiment ? true : false)" [forProblemType]="(forExperiment ? forExperiment.type : ProblemType.Regression)" (editEvent)="onFileChange()"></app-form-model>
<app-form-dataset [ngClass]="{'form-hidden': type != FolderType.Dataset}" [forExperiment]="forExperiment" (editEvent)="onFileChange()"></app-form-dataset>
</div>
@@ -160,4 +149,20 @@
</button>
</ng-container>
</div>
+ <div [ngSwitch]="newFileSelected" *ngIf="!listView">
+ <div class="file-bottom-buttons" *ngIf="selectedTab != TabType.NewFile">
+ <div class="file-bottom-buttons-helper">
+ <button *ngIf="this.selectedFile && selectedTab == TabType.File && privacy != Privacy.Public" class="btn-clear file-button" (click)="deleteFile(this.selectedFile, $event)">
+ <mat-icon matTooltip="Obriši" matTooltipPosition="right">delete</mat-icon>
+ </button>
+ <button *ngIf="this.selectedFile && selectedTab==TabType.File && FolderType.Dataset==this.type" class="btn-clear file-button" (click)="downloadFile(this.selectedFile,$event)" style="display: inline-block;">
+ <mat-icon matTooltip="Preuzmi" matTooltipPosition="before">download</mat-icon>
+ </button>
+ </div>
+ <!-- <button class="btn-clear file-button">
+ <mat-icon>zoom_out_map</mat-icon>
+ </button> -->
+ </div>
+ </div>
+
</div> \ No newline at end of file
diff --git a/frontend/src/app/_elements/folder/folder.component.ts b/frontend/src/app/_elements/folder/folder.component.ts
index c9252caa..93ef9043 100644
--- a/frontend/src/app/_elements/folder/folder.component.ts
+++ b/frontend/src/app/_elements/folder/folder.component.ts
@@ -336,22 +336,41 @@ export class FolderComponent implements AfterViewInit {
case FolderType.Dataset:
const dataset = <Dataset>file;
Shared.openYesNoDialog("Obriši izvor podataka", "Eksperimenti i trenirani modeli nad ovim izvorom podataka će takođe biti obrisani, da li ste sigurni da želite da obrišete izvor: " + dataset.name + "?", () => {
+ if(this.selectedTab==TabType.MyDatasets){
this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1);
this.files.splice(this.files.indexOf(file), 1);
+ }
this.loadingAction = true;
this.datasetsService.deleteDataset(dataset).subscribe((response) => {
this.loadingAction = false;
+ if(this.selectedTab==TabType.File){
+ this.refreshDatasets(null);
+ this.selectedFile=undefined!;
+ setTimeout(() => {
+ this.selectTab(TabType.MyDatasets);
+ });
+ }
+
});
})
break;
case FolderType.Model:
const model = <Model>file;
Shared.openYesNoDialog("Obriši konfiguraciju neuronske mreže", "Trenirani modeli za ovu konfiguraciju će takođe biti obrisani, da li ste sigurni da želite da obrišete konfiguraciju: " + model.name + "?", () => {
+ if(this.selectedTab==TabType.MyModels){
this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1);
this.files.splice(this.files.indexOf(file), 1);
+ }
this.loadingAction = true;
this.modelsService.deleteModel(<Model>file).subscribe((response) => {
this.loadingAction = false;
+ if(this.selectedTab==TabType.File){
+ this.refreshModels(null);
+ this.selectedFile=undefined!;
+ setTimeout(() => {
+ this.selectTab(TabType.MyModels);
+ });
+ }
});
})
@@ -370,11 +389,20 @@ export class FolderComponent implements AfterViewInit {
} else {
const experiment = <Experiment>file;
Shared.openYesNoDialog("Obriši eksperiment", "Trenirani modeli za ovaj eksperiment će takođe biti obrisani, da li ste sigurni da želite da obrišete eksperiment: " + experiment.name + "?", () => {
+ if(this.selectedTab==TabType.MyExperiments){
this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1);
this.files.splice(this.files.indexOf(file), 1);
+ }
this.loadingAction = true;
this.experimentsService.deleteExperiment(experiment).subscribe((response) => {
- this.loadingAction = false;
+ this.loadingAction = false;
+ if(this.selectedTab==TabType.File){
+ this.refreshExperiments();
+ this.selectedFile=undefined!;
+ setTimeout(() => {
+ this.selectTab(TabType.MyExperiments);
+ });
+ }
});
});
}
diff --git a/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.css b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.css
new file mode 100644
index 00000000..551a4e21
--- /dev/null
+++ b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.css
@@ -0,0 +1,21 @@
+#btnYes {
+ background-color: var(--offwhite);
+ color: var(--ns-bg-dark-100);
+}
+
+#btnNo {
+ color: gray;
+}
+
+.wrongInput {
+ color: var(--ns-warn);
+ font-size: 11px;
+}
+
+::ng-deep.mat-dialog-content {
+ overflow: visible;
+}
+
+.hidden-class {
+ opacity: 0;
+} \ No newline at end of file
diff --git a/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.html b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.html
new file mode 100644
index 00000000..db44dfe1
--- /dev/null
+++ b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.html
@@ -0,0 +1,24 @@
+<h1 mat-dialog-title class="text-center">Sačuvaj izmene</h1>
+<div mat-dialog-content class="mt-5 mb-3 mx-1">
+ <form (keydown)="saveWithEnterKey($event)">
+ <mat-radio-group [(ngModel)]="selectedOption" [ngModelOptions]="{standalone: true}">
+ <!-- I Update the existing experiment -->
+ <mat-radio-button [value]="1" checked>Izmeni postojeći eksperiment</mat-radio-button>
+ <!-- II Save as new experiment -->
+ <mat-radio-button [value]="2" class="mt-4">Sačuvaj kao novi eksperiment</mat-radio-button>
+ </mat-radio-group>
+ <div class="d-flex align-items-center justify-content-center mt-3" [ngClass]="{'hidden-class': selectedName.length == 0 && selectedOption == 1}">
+ <mat-form-field [style.width.px]=200>
+ <input type="text" matInput [(ngModel)]="selectedName" (click)="selectedOption = 2" (keydown)="selectedOption = 2" cdkFocusInitial [ngModelOptions]="{standalone: true}" placeholder="Naziv novog eskperimenta">
+ </mat-form-field>
+ </div>
+ <div class="d-flex align-items-center justify-content-center mt-1 mx-4">
+ <p *ngIf="wrongAlreadyExists" class="wrongInput">Eskperiment sa unetim nazivom već postoji u kolekciji.<br>Izaberite drugi naziv.</p>
+ <p *ngIf="wrongEmptyName" class="wrongInput">Unesite naziv eksperimenta.</p>
+ </div>
+ </form>
+</div>
+<div mat-dialog-actions class="justify-content-center">
+ <button id="btnYes" mat-stroked-button color="basic" (click)="onYesClick()">Sačuvaj</button>
+ <button id="btnNo" mat-stroked-button (click)="onNoClick()">Odustani</button>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.spec.ts b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.spec.ts
new file mode 100644
index 00000000..e0f26b2c
--- /dev/null
+++ b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { UpdateExperimentDialogComponent } from './update-experiment-dialog.component';
+
+describe('UpdateExperimentDialogComponent', () => {
+ let component: UpdateExperimentDialogComponent;
+ let fixture: ComponentFixture<UpdateExperimentDialogComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ UpdateExperimentDialogComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(UpdateExperimentDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.ts b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.ts
new file mode 100644
index 00000000..068aa2ef
--- /dev/null
+++ b/frontend/src/app/_modals/update-experiment-dialog/update-experiment-dialog.component.ts
@@ -0,0 +1,68 @@
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import Experiment from 'src/app/_data/Experiment';
+import { ExperimentsService } from 'src/app/_services/experiments.service';
+
+interface DialogData {
+ experiment: Experiment;
+ selectedOption: number;
+}
+
+@Component({
+ selector: 'app-update-experiment-dialog',
+ templateUrl: './update-experiment-dialog.component.html',
+ styleUrls: ['./update-experiment-dialog.component.css']
+})
+export class UpdateExperimentDialogComponent implements OnInit {
+
+ selectedOption: number = 1;
+ selectedName: string = '';
+ wrongAlreadyExists: boolean = false;
+ wrongEmptyName: boolean = false;
+
+ constructor(public dialogRef: MatDialogRef<UpdateExperimentDialogComponent>, @Inject(MAT_DIALOG_DATA) public data: DialogData, private experimentService: ExperimentsService) {
+ this.wrongAlreadyExists = false;
+ this.wrongEmptyName = false;
+ }
+
+ ngOnInit(): void {
+ }
+
+ onNoClick() {
+ this.dialogRef.close();
+ }
+
+ saveWithEnterKey(keyboardEvent: KeyboardEvent) {
+ if (keyboardEvent.code == "Enter" || keyboardEvent.code == "NumpadEnter")
+ this.onYesClick();
+ }
+
+ onYesClick() {
+ if (this.selectedOption == 1) { //update
+ this.experimentService.updateExperiment(this.data.experiment).subscribe((response) => {
+ this.data.experiment = response;
+ this.dialogRef.close(this.data.experiment);
+ });
+ }
+ else { //save new
+ if (this.selectedName == "") {
+ this.wrongEmptyName = true;
+ return;
+ }
+ this.wrongEmptyName = false;
+
+ const newExperiment = new Experiment();
+ Object.assign(newExperiment, this.data.experiment);
+ newExperiment.name = this.selectedName;
+ newExperiment._id = '';
+ this.experimentService.addExperiment(newExperiment!).subscribe((response) => {
+ this.wrongAlreadyExists = false;
+ this.dialogRef.close(response);
+ }, (error) => {
+ if (error.error == "Experiment with this name exists") {
+ this.wrongAlreadyExists = true;
+ }
+ });
+ }
+ }
+}
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index 89d53115..e2823761 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -22,6 +22,7 @@ import { YesNoDialogComponent } from './_modals/yes-no-dialog/yes-no-dialog.comp
import { EncodingDialogComponent } from './_modals/encoding-dialog/encoding-dialog.component';
import { MissingvaluesDialogComponent } from './_modals/missingvalues-dialog/missingvalues-dialog.component';
import { SaveExperimentDialogComponent } from './_modals/save-experiment-dialog/save-experiment-dialog.component';
+import { UpdateExperimentDialogComponent } from './_modals/update-experiment-dialog/update-experiment-dialog.component';
// Pages
import { HomeComponent } from './_pages/home/home.component';
import { ProfileComponent } from './_pages/profile/profile.component';
@@ -93,7 +94,8 @@ export function initializeApp(appConfig: Configuration) {
MetricViewComponent,
LineChartComponent,
SaveExperimentDialogComponent,
- SpinnerComponent
+ SpinnerComponent,
+ UpdateExperimentDialogComponent
],
imports: [
BrowserModule,