diff options
Diffstat (limited to 'frontend/src')
10 files changed, 201 insertions, 118 deletions
diff --git a/frontend/src/app/_data/Dataset.ts b/frontend/src/app/_data/Dataset.ts index 4ff0a471..87b09c6f 100644 --- a/frontend/src/app/_data/Dataset.ts +++ b/frontend/src/app/_data/Dataset.ts @@ -29,15 +29,15 @@ export class ColumnInfo { public columnName: string = '', public isNumber: boolean = false, public numNulls: number = 0, - public uniqueValues?: string[], - public uniqueValuesCount?: number[], - public uniqueValuesPercent?: number[], - public median?: number, - public mean?: number, - public min?: number, - public max?: number, - public q1?: number, - public q3?: number, + public uniqueValues: string[]=[], + public uniqueValuesCount: number[]=[], + public uniqueValuesPercent: number[]=[], + public median: number=0, + public mean: number=0, + public min: number=0, + public max: number=0, + public q1: number=0, + public q3: number=0, ) { /*if (isNumber) this.columnType = ColumnType.numerical; diff --git a/frontend/src/app/_elements/_charts/box-plot/box-plot.component.ts b/frontend/src/app/_elements/_charts/box-plot/box-plot.component.ts index 9addd6bb..bf5e3fd6 100644 --- a/frontend/src/app/_elements/_charts/box-plot/box-plot.component.ts +++ b/frontend/src/app/_elements/_charts/box-plot/box-plot.component.ts @@ -16,22 +16,31 @@ Chart.register(BoxPlotController, BoxAndWiskers, LinearScale, CategoryScale); }) export class BoxPlotComponent implements AfterViewInit { - @Input()width?: number; - @Input()height?: number; - @Input()mean?: number; - @Input()median?: number; - @Input()min?: number; - @Input()max?: number; - @Input()q1?: number; - @Input()q3?: number; + @Input() width?: number; + @Input() height?: number; + @Input() mean?: number; + @Input() median?: number; + @Input() min?: number; + @Input() max?: number; + @Input() q1?: number; + @Input() q3?: number; + + updateChart(min: number, max: number, q1: number, q3: number, median: number) { + if (this.myChart) { + this.boxplotData.datasets[0].data = [[min, q1, median, q3, max]] + this.myChart.update(); + } + }; @ViewChild('boxplot') chartRef!: ElementRef; - constructor() { } + constructor() { + //this.updateChart(); + } boxplotData = { // define label tree - labels: ['January'/*, 'February', 'March', 'April', 'May', 'June', 'July'*/], - datasets: [{ + //labels: ['January'/*, 'February', 'March', 'April', 'May', 'June', 'July'*/], + datasets: [{ label: 'Dataset 1', backgroundColor: '#0063AB', borderColor: '#dfd7d7', @@ -41,68 +50,43 @@ export class BoxPlotComponent implements AfterViewInit { padding: 10, itemRadius: 0, data: [ - randomValues(100, 0, 100), - /*randomValues(100, 0, 20), - randomValues(100, 20, 70), - randomValues(100, 60, 100), - randomValues(40, 50, 100), - randomValues(100, 60, 120), - randomValues(100, 80, 100)*/ - ]}/*, { - label: 'Dataset 2', - backgroundColor: 'rgba(0,0,255,0.5)', - borderColor: 'blue', - borderWidth: 1, - outlierColor: '#999999', - padding: 10, - itemRadius: 0, - data: [ - randomValues(100, 60, 100), - randomValues(100, 0, 100), - randomValues(100, 0, 20), - randomValues(100, 20, 70), - randomValues(40, 60, 120), - randomValues(100, 20, 100), - randomValues(100, 80, 100) - ] - }*/] - }; + randomValues(100, 0, 100), + ] + }] + }; ngAfterViewInit(): void { - const myChart = new Chart(this.chartRef.nativeElement, { - type: "boxplot", - data: this.boxplotData, - options: { - /*title: { - display: true, - text: 'Predicted world population (millions) in 2050' - }*/ - plugins:{ - legend: { - display: false - }, - }, - scales : { - x: { - ticks: { - color: '#dfd7d7' - }, - grid: { - color: "rgba(0, 99, 171, 0.5)" - } - }, - y : { - min: -50, - max: 200, - ticks: { - color: '#dfd7d7' - }, - grid: { - color: "rgba(0, 99, 171, 0.5)" - } - } + this.myChart = new Chart(this.chartRef.nativeElement, { + type: "boxplot", + data: this.boxplotData, + options: { + plugins: { + legend: { + display: false + }, + }, + scales: { + x: { + ticks: { + color: '#dfd7d7' + }, + grid: { + color: "rgba(0, 99, 171, 0.5)" + } + }, + y: { + min: this.min, + max: this.max, + ticks: { + color: '#dfd7d7' + }, + grid: { + color: "rgba(0, 99, 171, 0.5)" + } } - } - }); -} + } + } + }); + } + myChart?: Chart; } diff --git a/frontend/src/app/_elements/_charts/pie-chart/pie-chart.component.ts b/frontend/src/app/_elements/_charts/pie-chart/pie-chart.component.ts index 932ed963..c2bd3262 100644 --- a/frontend/src/app/_elements/_charts/pie-chart/pie-chart.component.ts +++ b/frontend/src/app/_elements/_charts/pie-chart/pie-chart.component.ts @@ -12,21 +12,34 @@ export class PieChartComponent implements AfterViewInit { @Input()height?: number; @Input()uniqueValues?: string[] = []; @Input()uniqueValuesPercent?: number[] = []; + + updatePieChart(uniqueValues: string[], uniqueValuesPercent: number[]){ + console.log(this.uniqueValues, this.uniqueValuesPercent); + const newPieChartData = { + datasets: [{ + label: "Population (millions)", + backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"], + data: [2478,5267,734,784,433], + }] + + } + }; @ViewChild('piechart') chartRef!: ElementRef; constructor() { } + pieChartData = { + datasets: [{ + label: "Population (millions)", + backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"], + data: [2478,5267,734,784,433] + }] +} + ngAfterViewInit(): void { const myChart = new Chart(this.chartRef.nativeElement, { type: 'pie', - data: { - labels: ["Africa", "Asia", "Europe", "Latin America", "North America"], - datasets: [{ - label: "Population (millions)", - backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"], - data: [2478,5267,734,784,433], - }] - }, + data: this.pieChartData, options: { /*title: { display: true, @@ -38,11 +51,9 @@ export class PieChartComponent implements AfterViewInit { }, }, layout: { - padding: 15} + padding: 15 + } } -}); - - } + });} - -} +}
\ No newline at end of file diff --git a/frontend/src/app/_elements/column-table/column-table.component.html b/frontend/src/app/_elements/column-table/column-table.component.html index 59c1899b..d07d50b2 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.html +++ b/frontend/src/app/_elements/column-table/column-table.component.html @@ -143,6 +143,9 @@ <td *ngFor="let colInfo of dataset.columnInfo; let i = index" class="pad-fix" [ngClass]="{'text-disabled' : !columnsChecked[i]}"> <mat-form-field> <mat-select matNativeControl [(value)]="experiment.encodings[i].encoding" [disabled]="!columnsChecked[i] || experiment.columnTypes[i] == ColumnType.numerical || colInfo.columnName == experiment.outputColumn" (selectionChange)="columnTableChangeDetected()"> + <mat-option [value]="Encoding.Label" *ngIf="experiment.columnTypes[i] == ColumnType.numerical || colInfo.columnName == experiment.outputColumn" [selected]="experiment.columnTypes[i] == ColumnType.numerical || colInfo.columnName == experiment.outputColumn"> + Nema enkodiranja + </mat-option> <mat-option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" [value]="option"> {{ optionName }} </mat-option> 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 44a15f22..d61c2537 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.ts +++ b/frontend/src/app/_elements/column-table/column-table.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChildren } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnInit, Output, QueryList, ViewChildren } from '@angular/core'; import Dataset from 'src/app/_data/Dataset'; import Experiment, { ColumnEncoding, Encoding, ColumnType, NullValueOptions } from 'src/app/_data/Experiment'; import { DatasetsService } from 'src/app/_services/datasets.service'; @@ -12,6 +12,8 @@ import { ExperimentsService } from 'src/app/_services/experiments.service'; import { SaveExperimentDialogComponent } from 'src/app/_modals/save-experiment-dialog/save-experiment-dialog.component'; import { AlertDialogComponent } from 'src/app/_modals/alert-dialog/alert-dialog.component'; import Shared from 'src/app/Shared'; +import { PieChartComponent } from '../_charts/pie-chart/pie-chart.component'; +import { BoxPlotComponent } from '../_charts/box-plot/box-plot.component'; @Component({ selector: 'app-column-table', @@ -20,6 +22,8 @@ import Shared from 'src/app/Shared'; }) export class ColumnTableComponent implements AfterViewInit { + @ViewChildren(BoxPlotComponent) boxplotComp!: QueryList<BoxPlotComponent>; + @ViewChildren(PieChartComponent) piechartComp!: QueryList<PieChartComponent>; @Input() dataset?: Dataset; @Input() experiment!: Experiment; @Output() okPressed: EventEmitter<string> = new EventEmitter(); @@ -42,9 +46,36 @@ export class ColumnTableComponent implements AfterViewInit { //ovo mi nece trebati jer primam dataset iz druge komponente } + updateCharts() { + //min: number, max: number, q1: number, q3: number, median: number + let i = 0; + this.boxplotComp.changes.subscribe(() => { + const bps = this.boxplotComp.toArray(); + this.dataset?.columnInfo.forEach(colInfo => { + if (this.experiment.columnTypes[i] == ColumnType.numerical) { + bps[i].updateChart(colInfo!.min, colInfo.max, colInfo.q1, colInfo.q3, colInfo.median); + i++; + } + }); + }); + } + + updatePieChart(){ + //min: number, max: number, q1: number, q3: number, median: number + let i=0; + const pieChart = this.piechartComp.toArray(); + this.dataset?.columnInfo.forEach(colInfo => + { if (this.experiment.columnTypes[i] == ColumnType.categorical) + { + pieChart[i].updatePieChart(colInfo!.uniqueValues, colInfo.uniqueValuesPercent); + i++; + } + }); + } + loadDataset(dataset: Dataset) { + console.log("LOADED DATASET"); this.dataset = dataset; - this.setColumnTypeInitial(); this.dataset.columnInfo.forEach(column => { @@ -67,9 +98,13 @@ export class ColumnTableComponent implements AfterViewInit { } }); this.loaded = true; + + this.updateCharts(); + this.updatePieChart(); } ngAfterViewInit(): void { + console.log(this.dataset?.columnInfo); } @@ -92,7 +127,7 @@ export class ColumnTableComponent implements AfterViewInit { resetOutputColumn() { if (this.experiment.inputColumns.length > 0) this.experiment.outputColumn = this.experiment.inputColumns[0]; - else + else this.experiment.outputColumn = '-'; } @@ -140,7 +175,7 @@ export class ColumnTableComponent implements AfterViewInit { if (columnName == this.experiment.outputColumn) { if (this.experiment.inputColumns.length > 0) this.experiment.outputColumn = this.experiment.inputColumns[0]; - else + else this.experiment.outputColumn = '-'; } } @@ -167,20 +202,30 @@ export class ColumnTableComponent implements AfterViewInit { resetColumnEncodings(encodingType: Encoding) { if (this.experiment != undefined && this.dataset != undefined) { this.experiment.encodings = []; - for (let i = 0; i < this.dataset?.columnInfo.length; i++) { + for (let i = 0; i < this.dataset.columnInfo.length; i++) { this.experiment.encodings.push(new ColumnEncoding(this.dataset?.columnInfo[i].columnName, encodingType)); //console.log(this.experiment.encodings); } this.columnTableChangeDetected(); } } + resetColumnEncodingsGlobalSetting(encodingType: Encoding) { + if (this.experiment != undefined && this.dataset != undefined) { + for (let i = 0; i < this.dataset.columnInfo.length; i++) { + if (this.experiment.columnTypes[i] == ColumnType.categorical && this.dataset.columnInfo[i].columnName != this.experiment.outputColumn) //promeni + this.experiment.encodings[i].encoding = encodingType; + } + this.columnTableChangeDetected(); + } + } openEncodingDialog() { const dialogRef = this.dialog.open(EncodingDialogComponent, { - width: '400px' + width: '400px', + data: { experiment: this.experiment, dataset: this.dataset } }); dialogRef.afterClosed().subscribe(selectedEncoding => { if (selectedEncoding != undefined) - this.resetColumnEncodings(selectedEncoding); + this.resetColumnEncodingsGlobalSetting(selectedEncoding); }); } @@ -228,7 +273,7 @@ export class ColumnTableComponent implements AfterViewInit { openSaveExperimentDialog() { const dialogRef = this.dialog.open(SaveExperimentDialogComponent, { width: '400px', - data: { experiment: this.experiment } + data: { experiment: this.experiment } }); dialogRef.afterClosed().subscribe(experiment => { if (experiment) { @@ -303,7 +348,7 @@ export class ColumnTableComponent implements AfterViewInit { Shared.openDialog("Upozorenje", "Kako bi eksperiment bio uspešno izveden, neophodno je da izaberete barem dve kolone koje ćete koristiti."); else if (this.experiment.inputColumns.length == 1) Shared.openDialog("Upozorenje", "Kako bi eksperiment bio uspešno izveden, neophodno je da izaberete barem dve kolone koje ćete koristiti (mora postojati bar jedna ulazna i jedna izlazna kolona)."); - else + else this.openSaveExperimentDialog(); } updateExperiment() { @@ -311,7 +356,7 @@ export class ColumnTableComponent implements AfterViewInit { Shared.openDialog("Upozorenje", "Kako bi eksperiment bio uspešno izveden, neophodno je da izaberete barem dve kolone koje ćete koristiti."); else if (this.experiment.inputColumns.length == 1) Shared.openDialog("Upozorenje", "Kako bi eksperiment bio uspešno izveden, neophodno je da izaberete barem dve kolone koje ćete koristiti (mora postojati bar jedna ulazna i jedna izlazna kolona)."); - else + else this.openUpdateExperimentDialog(); } @@ -367,3 +412,5 @@ export class Tab { public value: Table ) { } } + + diff --git a/frontend/src/app/_elements/form-dataset/form-dataset.component.html b/frontend/src/app/_elements/form-dataset/form-dataset.component.html index 055c3fd3..b96276bd 100644 --- a/frontend/src/app/_elements/form-dataset/form-dataset.component.html +++ b/frontend/src/app/_elements/form-dataset/form-dataset.component.html @@ -25,7 +25,7 @@ <div class="kolona"> <mat-form-field appearance="fill"> <mat-label>Delimiter</mat-label> - <mat-select id="delimiterOptions" [(ngModel)]="dataset.delimiter" (change)="update()" value=","> + <mat-select id="delimiterOptions" [(ngModel)]="dataset.delimiter" (selectionChange)="update()" value=","> <mat-option *ngFor="let option of delimiterOptions" [value]="option"> {{ option }} </mat-option> diff --git a/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.ts b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.ts index 231d81a6..9c45d7b6 100644 --- a/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.ts +++ b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.ts @@ -1,7 +1,10 @@ import { Component, OnInit } from '@angular/core'; -import { MatDialogRef } from '@angular/material/dialog'; -import { Encoding } from 'src/app/_data/Experiment'; - +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { ColumnType, Encoding } from 'src/app/_data/Experiment'; +import Experiment from 'src/app/_data/Experiment'; +import { ExperimentsService } from 'src/app/_services/experiments.service'; +import { Inject} from '@angular/core'; +import Dataset from 'src/app/_data/Dataset'; @Component({ selector: 'app-encoding-dialog', @@ -13,6 +16,7 @@ export class EncodingDialogComponent implements OnInit { selectedEncodingType?: Encoding; Encoding = Encoding; Object = Object; + categoricalColumnExists: boolean = true; constructor(public dialogRef: MatDialogRef<EncodingDialogComponent>) { @@ -20,6 +24,7 @@ export class EncodingDialogComponent implements OnInit { } ngOnInit(): void { + } onNoClick() { diff --git a/frontend/src/app/_pages/experiment/experiment.component.css b/frontend/src/app/_pages/experiment/experiment.component.css index 36c35484..4c063f87 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.css +++ b/frontend/src/app/_pages/experiment/experiment.component.css @@ -52,4 +52,16 @@ mat-stepper { width: 98%; height: 98%; overflow-y: auto; -}
\ No newline at end of file +} +.ekspName{ + font-weight: bold; + font-size: large; +} + + +.addedElement{ + color:var(--ns-accent); +} +.text-overflow { + overflow-wrap: break-word; +} diff --git a/frontend/src/app/_pages/experiment/experiment.component.html b/frontend/src/app/_pages/experiment/experiment.component.html index 28bacf1f..a2ede838 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.html +++ b/frontend/src/app/_pages/experiment/experiment.component.html @@ -1,28 +1,48 @@ <div class="container-fluid p-0 text-offwhite holder" style="height: calc(100vh - 64px); text-align: center;"> <div class="d-flex flex-colum align-items-center sidenav"> + <div> + <div class="ekspName " style="width: 250px;"> + <div class="text-overflow" *ngIf="experiment.name=='exp1'" style="width: 250px;"> + Novi Eksperiment + </div> + <div class="text-overflow" *ngIf="experiment.name!='exp1'" style="width: 250px;"> + {{experiment.name}} + </div> + + </div> <mat-stepper orientation="vertical" (selectionChange)="changePage($event)"> <mat-step> <!--editable="false"--> - <ng-template matStepLabel><span class="label">Izvor podataka</span></ng-template> + <ng-template matStepLabel> + <span class="label" *ngIf="dataset==undefined">Izvor podataka</span> + <span class="label addedElement" *ngIf="dataset!=undefined">{{dataset.name}}</span> + </ng-template> <ng-template matStepContent> - <p>Izaberite vas izvor podataka</p> + <p class="text-left">Izaberite vas izvor podataka</p> </ng-template> </mat-step> <mat-step> - <ng-template matStepLabel> <span class="label">Odabir kolona</span></ng-template> + <ng-template matStepLabel> + <span class="label addedElement" *ngIf="experiment.name!='exp1'">Predvideti:{{experiment.outputColumn}}</span> + <span class="label" *ngIf="experiment.name=='exp1'">Odabir kolona</span> + </ng-template> <ng-template matStepContent> - <p>Pripremite podatke i izaberite izlazne kolone</p> + <p class="text-left">Pripremite podatke i izaberite izlazne kolone</p> </ng-template> </mat-step> <mat-step> - <ng-template matStepLabel><span class="label">Treniranje</span></ng-template> - <p>Odaberite parametre i trenirajte model</p> + <ng-template matStepLabel> + <span class="label addedElement" *ngIf="modelToTrain!=undefined">{{modelToTrain.name}}</span> + <span class="label" *ngIf="modelToTrain==undefined">Treniranje</span> + </ng-template> + <p class="text-left">Odaberite parametre i trenirajte model</p> </mat-step> <mat-step> <ng-template matStepLabel><span class="label">Pregled rezultata treniranja</span></ng-template> - <p>Pregledajte tok treniranja i grafički prikaz rezultata</p> + <p class="text-left">Pregledajte tok treniranja i grafički prikaz rezultata</p> </mat-step> </mat-stepper> + </div> </div> <div #stepsContainer class="steps-container"> <div #steps id="step_1" class="step-content"> @@ -46,4 +66,4 @@ </div> </div> </div> -</div>
\ No newline at end of file +</div> diff --git a/frontend/src/app/_pages/experiment/experiment.component.ts b/frontend/src/app/_pages/experiment/experiment.component.ts index 97029565..abf4b697 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.ts +++ b/frontend/src/app/_pages/experiment/experiment.component.ts @@ -157,6 +157,7 @@ export class ExperimentComponent implements AfterViewInit { this.dataset = d; this.columnTable.loadDataset(this.dataset); + } modelToTrain?: Model; |