aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/app/_pages
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/app/_pages')
-rw-r--r--frontend/src/app/_pages/experiment/experiment.component.css30
-rw-r--r--frontend/src/app/_pages/experiment/experiment.component.html27
-rw-r--r--frontend/src/app/_pages/experiment/experiment.component.ts104
-rw-r--r--frontend/src/app/_pages/page-dataset/page-dataset.component.css0
-rw-r--r--frontend/src/app/_pages/page-dataset/page-dataset.component.html4
-rw-r--r--frontend/src/app/_pages/page-dataset/page-dataset.component.spec.ts25
-rw-r--r--frontend/src/app/_pages/page-dataset/page-dataset.component.ts45
-rw-r--r--frontend/src/app/_pages/page-model/page-model.component.css0
-rw-r--r--frontend/src/app/_pages/page-model/page-model.component.html6
-rw-r--r--frontend/src/app/_pages/page-model/page-model.component.spec.ts25
-rw-r--r--frontend/src/app/_pages/page-model/page-model.component.ts41
11 files changed, 291 insertions, 16 deletions
diff --git a/frontend/src/app/_pages/experiment/experiment.component.css b/frontend/src/app/_pages/experiment/experiment.component.css
index 59e004e9..37edd3c2 100644
--- a/frontend/src/app/_pages/experiment/experiment.component.css
+++ b/frontend/src/app/_pages/experiment/experiment.component.css
@@ -74,4 +74,34 @@ mat-stepper {
.text-overflow-experiment-name {
overflow-wrap: break-word;
+}
+
+#compareButton {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+}
+
+.side-by-side {
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+ height: 100%;
+}
+
+
+/* one item */
+
+.side-by-side>*:first-child:nth-last-child(1) {
+ /* -or- li:only-child { */
+ width: 100%;
+}
+
+
+/* two items */
+
+.side-by-side>*:first-child:nth-last-child(2),
+.side-by-side>*:first-child:nth-last-child(2)~li {
+ width: 50%;
+ margin: 5px;
} \ No newline at end of file
diff --git a/frontend/src/app/_pages/experiment/experiment.component.html b/frontend/src/app/_pages/experiment/experiment.component.html
index 17a6539d..3176f58c 100644
--- a/frontend/src/app/_pages/experiment/experiment.component.html
+++ b/frontend/src/app/_pages/experiment/experiment.component.html
@@ -25,10 +25,10 @@
<ng-template matStepLabel>
<span class="label addedElement text-overflow" *ngIf="experiment._id!=''">Predvideti:{{experiment.outputColumn}}</span>
<span *ngIf="!this.step1" class="align-middle"><mat-icon>lock</mat-icon></span>
- <span class="label text-overflow" *ngIf="experiment._id==''">Odabir kolona </span>
+ <span class="label text-overflow" *ngIf="experiment._id==''">Priprema podataka </span>
</ng-template>
<ng-template matStepContent>
- <p class="text-left text-overflow">Pripremite podatke i izaberite izlazne kolone</p>
+ <p class="text-left text-overflow">Pripremite podatke i odaberite ulazne i izlaznu kolonu</p>
</ng-template>
</mat-step>
<mat-step [completed]="this.step3">
@@ -57,18 +57,35 @@
</div>
<div #steps id="step_2" class="step-content" *ngIf="step1">
<div class="step-content-inside">
- <app-column-table (okPressed)="goToPage(2); experiment._columnsSelected = true;" (columnTableChanged)="columnTableChangedEvent()" (experimentChanged)="experimentChangedEvent()" [experiment]="experiment" [dataset]="dataset"></app-column-table>
+ <app-column-table (columnTableChanged)="columnTableChangedEvent()" (experimentChanged)="experimentChangedEvent()" [experiment]="experiment" [dataset]="dataset"></app-column-table>
</div>
</div>
<div #steps id="step_3" class="step-content" *ngIf="step2">
<div class="step-content-inside">
- <app-folder #folderModel [type]="FolderType.Model" [forExperiment]="experiment" [startingTab]="TabType.NewFile" [tabsToShow]="[TabType.MyModels]" (okPressed)="goToPage(3); trainModel();" (selectedFileChanged)="setModel($event)"></app-folder>
+ <div id="compareButton">
+ <button mat-raised-button color="accent" *ngIf="!comparing" (click)="toggleCompare()"><mat-icon>compare</mat-icon> Dodaj konfiguraciju za upoređivanje</button>
+ <button mat-raised-button *ngIf="comparing" (click)="toggleCompare()"><mat-icon>not_interested</mat-icon> Prekini upoređivanje</button>
+ </div>
+ <div class="side-by-side">
+ <app-folder #folderModel [type]="FolderType.Model" [forExperiment]="experiment" [startingTab]="TabType.NewFile" [tabsToShow]="[TabType.MyModels]" (okPressed)="trainModel();" (selectedFileChanged)="setModel($event);"></app-folder>
+ <app-folder #folderModelCompare [type]="FolderType.Model" [forExperiment]="experiment" [startingTab]="TabType.MyModels" [tabsToShow]="[TabType.MyModels]" (okPressed)=" trainModelCmp();" (selectedFileChanged)="setModelCmp($event);" style="width: 50%;"
+ *ngIf="comparing"></app-folder>
+ </div>
</div>
</div>
<div #steps id="step_4" class="step-content" *ngIf="step3">
<div class="step-content-inside">
- <app-metric-view #metricView></app-metric-view>
+ <div class="side-by-side">
+ <app-line-chart #linechart [experiment]="experiment" [predictor]="predictor!"></app-line-chart>
+ <app-line-chart #linechartCompare [experiment]="experiment" style="width: 50%;" *ngIf="comparing"></app-line-chart>
+ </div>
</div>
</div>
+ <!--
+ <div #steps id="step_5" class="step-content" *ngIf="step4">
+ <div class="step-content-inside">
+ <app-form-predictor></app-form-predictor>
+ </div>
+ </div>-->
</div>
</div> \ No newline at end of file
diff --git a/frontend/src/app/_pages/experiment/experiment.component.ts b/frontend/src/app/_pages/experiment/experiment.component.ts
index ec4275fa..e4d444b2 100644
--- a/frontend/src/app/_pages/experiment/experiment.component.ts
+++ b/frontend/src/app/_pages/experiment/experiment.component.ts
@@ -15,6 +15,8 @@ import { MetricViewComponent } from 'src/app/_elements/metric-view/metric-view.c
import { ActivatedRoute, Router } from '@angular/router';
import { DatasetsService } from 'src/app/_services/datasets.service';
import { PredictorsService } from 'src/app/_services/predictors.service';
+import { LineChartComponent } from 'src/app/_elements/_charts/line-chart/line-chart.component';
+import Predictor from 'src/app/_data/Predictor';
@Component({
selector: 'app-experiment',
@@ -30,16 +32,32 @@ export class ExperimentComponent implements AfterViewInit {
event: number = 0;
experiment: Experiment;
dataset?: Dataset;
+ predictor?: Predictor;
+
@ViewChild("folderDataset") folderDataset!: FolderComponent;
@ViewChild(ColumnTableComponent) columnTable!: ColumnTableComponent;
@ViewChild("folderModel") folderModel!: FolderComponent;
- @ViewChild("metricView") metricView!: MetricViewComponent;
+ @ViewChild("folderModelCompare") folderModelCmp!: FolderComponent;
+ @ViewChild("linechart") linechartComponent!: LineChartComponent;
+ @ViewChild("linechartCompare") linechartComponentCmp!: LineChartComponent;
step1: boolean = false;
step2: boolean = false;
step3: boolean = false;
step4: boolean = false;
+ comparing: boolean = false;
+
+ toggleCompare() {
+ this.comparing = !this.comparing;
+ setTimeout(() => {
+ if (this.folderModel.formModel)
+ this.folderModel.formModel.graph.resize();
+ if (this.folderModel.formNewModel)
+ this.folderModel.formNewModel.graph.resize();
+ });
+ }
+
constructor(private experimentsService: ExperimentsService, private modelsService: ModelsService, private datasetsService: DatasetsService, private predictorsService: PredictorsService, private signalRService: SignalRService, private route: ActivatedRoute) {
this.experiment = new Experiment("exp1");
}
@@ -57,7 +75,22 @@ export class ExperimentComponent implements AfterViewInit {
Shared.openDialog('Greška', 'Morate odabrati konfiguraciju neuronske mreže');
} else {
this.modelsService.trainModel(this.modelToTrain._id, this.experiment._id).subscribe(() => { console.log("pocelo treniranje") });
- this.step4 = true;
+ this.step3 = true;
+ setTimeout(() => {
+ this.goToPage(3);
+ });
+ }
+ }
+
+ trainModelCmp() {
+ if (!this.modelToTrainCmp) {
+ Shared.openDialog('Greška', 'Morate odabrati konfiguraciju neuronske mreže');
+ } else {
+ this.modelsService.trainModel(this.modelToTrainCmp._id, this.experiment._id).subscribe(() => { console.log("pocelo treniranje") });
+ this.step3 = true;
+ setTimeout(() => {
+ this.goToPage(3);
+ });
}
}
@@ -83,16 +116,48 @@ export class ExperimentComponent implements AfterViewInit {
if (this.signalRService.hubConnection) {
this.signalRService.hubConnection.on("NotifyEpoch", (mName: string, mId: string, stat: string, totalEpochs: number, currentEpoch: number) => {
- if (currentEpoch == 0) {
- this.history = [];
- }
+
if (this.modelToTrain?._id == mId) {
+ if (currentEpoch == 0) {
+ this.linechartComponent.setName(mName);
+ this.history = [];
+ }
+
stat = stat.replace(/'/g, '"');
this.history.push(JSON.parse(stat));
- this.metricView.update(this.history,this.modelToTrain.epochs);
+
+ this.linechartComponent.updateAll(this.history, this.modelToTrain.epochs);
+ }
+
+ if (this.modelToTrainCmp?._id == mId) {
+ if (currentEpoch == 0) {
+ this.linechartComponentCmp.setName(mName);
+ this.historyCmp = [];
+ }
+
+ stat = stat.replace(/'/g, '"');
+
+ this.historyCmp.push(JSON.parse(stat));
+ this.linechartComponentCmp.updateAll(this.historyCmp, this.modelToTrainCmp.epochs);
}
});
+ this.signalRService.hubConnection.on("NotifyPredictor", (pId: string, mId: string) => {
+ console.log("Predictor trained: ", pId, "for model:", mId);
+
+ if (this.modelToTrain && mId == this.modelToTrain._id) {
+ this.predictorsService.getPredictor(pId).subscribe((predictor) => {
+ this.linechartComponent.predictor = predictor;
+ });
+ }
+
+ if (this.modelToTrainCmp && mId == this.modelToTrainCmp._id) {
+ this.predictorsService.getPredictor(pId).subscribe((predictor) => {
+ this.linechartComponentCmp.predictor = predictor;
+ });
+ }
+ })
+
}
this.route.queryParams.subscribe(params => {
@@ -102,6 +167,7 @@ export class ExperimentComponent implements AfterViewInit {
if (predictorId != null) {
this.predictorsService.getPredictor(predictorId!).subscribe((response) => {
let predictor = response;
+ this.predictor = predictor;
this.experimentsService.getExperimentById(predictor.experimentId).subscribe((response) => {
this.experiment = response;
this.datasetsService.getDatasetById(this.experiment.datasetId).subscribe((response: Dataset) => {
@@ -111,11 +177,13 @@ export class ExperimentComponent implements AfterViewInit {
this.modelsService.getModelById(predictor.modelId).subscribe((response) => {
let model = response;
- this.folderModel.formModel.newModel = model;
+ this.folderModel.selectFile(model);
+ //this.folderModel.formModel.newModel = model;
this.step3 = true;
- let numOfEpochsArray = Array.from({length: model.epochs}, (_, i) => i + 1);
+ let numOfEpochsArray = Array.from({ length: model.epochs }, (_, i) => i + 1);
setTimeout(() => {
- this.metricView.linechartComponent.update(numOfEpochsArray, predictor.metricsAcc, predictor.metricsLoss, predictor.metricsMae, predictor.metricsMse, predictor.metricsValAcc, predictor.metricsValLoss, predictor.metricsValMae, predictor.metricsValMse);
+ this.linechartComponent.update(numOfEpochsArray, predictor.metricsAcc, predictor.metricsLoss, predictor.metricsMae, predictor.metricsMse, predictor.metricsValAcc, predictor.metricsValLoss, predictor.metricsValMae, predictor.metricsValMse);
+ this.goToPage(3);
})
});
});
@@ -129,6 +197,7 @@ export class ExperimentComponent implements AfterViewInit {
this.dataset = response;
this.folderDataset.forExperiment = this.experiment;
this.folderDataset.selectFile(this.dataset);
+ this.goToPage(1);
});
});
}
@@ -137,6 +206,7 @@ export class ExperimentComponent implements AfterViewInit {
}
history: any[] = [];
+ historyCmp: any[] = [];
updatePageIfScrolled() {
if (this.scrolling) return;
@@ -197,14 +267,18 @@ export class ExperimentComponent implements AfterViewInit {
this.step2 = true;
setTimeout(() => {
this.folderModel.updateExperiment();
+ this.folderModel.selectFile(undefined);
+ this.folderModel.selectTab(TabType.NewFile);
+ this.goToPage(2);
});
}
setDataset(dataset: FolderFile | null) {
- if (dataset == null) {
+ if (dataset == null ||dataset==undefined) {
this.columnTable.loaded = false;
this.dataset = undefined;
this.experiment.datasetId = '';
+ this.step1=false;
return;
}
const d = <Dataset>dataset;
@@ -215,13 +289,21 @@ export class ExperimentComponent implements AfterViewInit {
setTimeout(() => {
this.columnTable.loadDataset(d);
});
+ // REFRESH GRAFIKA (4. KORAKA) URADITI
}
modelToTrain?: Model;
+ modelToTrainCmp?: Model;
setModel(model: FolderFile) {
const m = <Model>model;
this.modelToTrain = m;
- this.step3 = true;
+ //this.step3 = true;
+ }
+
+ setModelCmp(model: FolderFile) {
+ const m = <Model>model;
+ this.modelToTrainCmp = m;
+ //this.step3 = true;
}
}
diff --git a/frontend/src/app/_pages/page-dataset/page-dataset.component.css b/frontend/src/app/_pages/page-dataset/page-dataset.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/page-dataset/page-dataset.component.css
diff --git a/frontend/src/app/_pages/page-dataset/page-dataset.component.html b/frontend/src/app/_pages/page-dataset/page-dataset.component.html
new file mode 100644
index 00000000..2357a656
--- /dev/null
+++ b/frontend/src/app/_pages/page-dataset/page-dataset.component.html
@@ -0,0 +1,4 @@
+<div class="force-centered" style="color: var(--offwhite);">
+ <app-form-dataset [disableAll]="true"></app-form-dataset>
+ <button mat-raised-button class="m-3 p-2" (click)="import()">Uvezi</button>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_pages/page-dataset/page-dataset.component.spec.ts b/frontend/src/app/_pages/page-dataset/page-dataset.component.spec.ts
new file mode 100644
index 00000000..2c961cd5
--- /dev/null
+++ b/frontend/src/app/_pages/page-dataset/page-dataset.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PageDatasetComponent } from './page-dataset.component';
+
+describe('PageDatasetComponent', () => {
+ let component: PageDatasetComponent;
+ let fixture: ComponentFixture<PageDatasetComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ PageDatasetComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PageDatasetComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_pages/page-dataset/page-dataset.component.ts b/frontend/src/app/_pages/page-dataset/page-dataset.component.ts
new file mode 100644
index 00000000..b6d0c2a4
--- /dev/null
+++ b/frontend/src/app/_pages/page-dataset/page-dataset.component.ts
@@ -0,0 +1,45 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import Shared from 'src/app/Shared';
+import Dataset from 'src/app/_data/Dataset';
+import { FormDatasetComponent } from 'src/app/_elements/form-dataset/form-dataset.component';
+import { DatasetsService } from 'src/app/_services/datasets.service';
+
+@Component({
+ selector: 'app-page-dataset',
+ templateUrl: './page-dataset.component.html',
+ styleUrls: ['./page-dataset.component.css']
+})
+export class PageDatasetComponent implements OnInit {
+
+ @ViewChild(FormDatasetComponent) formDataset!: FormDatasetComponent;
+
+ constructor(private route: ActivatedRoute, private router: Router, private datasetsService: DatasetsService) { }
+
+ ngOnInit(): void {
+ this.route.queryParams.subscribe(params => {
+ let id = this.route.snapshot.paramMap.get("id");
+ if (id) {
+ this.datasetsService.getDatasetById(id).subscribe((dataset) => {
+ this.formDataset.dataset = dataset;
+ this.formDataset.loadExisting();
+ });
+ } else {
+ this.router.navigate(['']);
+ }
+ });
+ }
+
+ import() {
+ this.formDataset.dataset._id = "";
+ this.formDataset.dataset.isPreProcess = true;
+ this.formDataset.dataset.isPublic = false;
+ this.datasetsService.stealDataset(this.formDataset.dataset).subscribe((response) => {
+ Shared.openDialog("Obaveštenje", "Uspešno ste dodali javni izvor podataka u vašu kolekciju.");
+ }, (error: any) => {
+ if (error.error == "Dataset with this name already exists") {
+ Shared.openDialog("Obaveštenje", "Izvor podataka sa ovim imenom postoji u vašoj kolekciji.");
+ }
+ });
+ }
+}
diff --git a/frontend/src/app/_pages/page-model/page-model.component.css b/frontend/src/app/_pages/page-model/page-model.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/page-model/page-model.component.css
diff --git a/frontend/src/app/_pages/page-model/page-model.component.html b/frontend/src/app/_pages/page-model/page-model.component.html
new file mode 100644
index 00000000..0ac8aaae
--- /dev/null
+++ b/frontend/src/app/_pages/page-model/page-model.component.html
@@ -0,0 +1,6 @@
+<div class="force-centered" style="color: var(--offwhite);">
+ <div>
+ {{JSON.stringify(model)}}
+ </div>
+ <button mat-raised-button class="m-3 p-2" (click)="import()">Uvezi</button>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_pages/page-model/page-model.component.spec.ts b/frontend/src/app/_pages/page-model/page-model.component.spec.ts
new file mode 100644
index 00000000..e235de5c
--- /dev/null
+++ b/frontend/src/app/_pages/page-model/page-model.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PageModelComponent } from './page-model.component';
+
+describe('PageModelComponent', () => {
+ let component: PageModelComponent;
+ let fixture: ComponentFixture<PageModelComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ PageModelComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PageModelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_pages/page-model/page-model.component.ts b/frontend/src/app/_pages/page-model/page-model.component.ts
new file mode 100644
index 00000000..0ccd0f9a
--- /dev/null
+++ b/frontend/src/app/_pages/page-model/page-model.component.ts
@@ -0,0 +1,41 @@
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import Shared from 'src/app/Shared';
+import Experiment from 'src/app/_data/Experiment';
+import Model from 'src/app/_data/Model';
+import { FormModelComponent } from 'src/app/_elements/form-model/form-model.component';
+import { ModelsService } from 'src/app/_services/models.service';
+
+@Component({
+ selector: 'app-page-model',
+ templateUrl: './page-model.component.html',
+ styleUrls: ['./page-model.component.css']
+})
+export class PageModelComponent implements OnInit {
+
+ constructor(private route: ActivatedRoute, private router: Router, private modelsService: ModelsService) { }
+ model!:Model;
+ ngOnInit(): void {
+ this.route.queryParams.subscribe(params => {
+ let id = this.route.snapshot.paramMap.get("id");
+ if (id) {
+ this.modelsService.getModelById(id).subscribe((model) => {
+ this.model = model;
+ });
+ } else {
+ this.router.navigate(['']);
+ }
+ });
+ }
+
+ import() {
+ this.model._id = "";
+ this.model.isPublic = false;
+ this.modelsService.stealModel(this.model).subscribe((response) => {
+ Shared.openDialog("Obaveštenje", "Uspešno ste dodali javnu konfiguraciju neuronske mreže u vašu kolekciju.");
+ }, (error: any) => {
+ Shared.openDialog("Obaveštenje", "Konfiguracija neuronske mreže sa ovim imenom postoji u vašoj kolekciji.");
+ });
+ }
+ JSON=JSON;
+}