diff options
author | TAMARA JERINIC <tamara.jerinic@gmail.com> | 2022-05-25 20:00:03 +0200 |
---|---|---|
committer | TAMARA JERINIC <tamara.jerinic@gmail.com> | 2022-05-25 20:00:03 +0200 |
commit | 8d96241a6958a5797d7bf203fbfb2bfe2a4ec391 (patch) | |
tree | 373ab9b113ecbe20bf6fad30ad4a7a860e3f4a69 | |
parent | 7dc17a7b94984d24829b6e30ee575e493f2ab787 (diff) | |
parent | 54a1eaf3b2176a41dcd2677eb64843638852c371 (diff) |
Merge branch 'redesign' of http://gitlab.pmf.kg.ac.rs/igrannonica/neuronstellar into redesign
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, |