diff options
Diffstat (limited to 'frontend/src')
16 files changed, 363 insertions, 9 deletions
diff --git a/frontend/src/app/_data/Dataset.ts b/frontend/src/app/_data/Dataset.ts index 766040a3..03060982 100644 --- a/frontend/src/app/_data/Dataset.ts +++ b/frontend/src/app/_data/Dataset.ts @@ -33,4 +33,4 @@ export class ColumnInfo { public min?: number, public max?: number ) { } -}
\ No newline at end of file +} diff --git a/frontend/src/app/_elements/column-table/column-table.component.css b/frontend/src/app/_elements/column-table/column-table.component.css index e69de29b..f65d7c3d 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.css +++ b/frontend/src/app/_elements/column-table/column-table.component.css @@ -0,0 +1,5 @@ +table { + display: block; + overflow-x: auto; + white-space: nowrap; +}
\ 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 7b18afc8..62699284 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.html +++ b/frontend/src/app/_elements/column-table/column-table.component.html @@ -1 +1,104 @@ -<p>column-table works!</p> +<table *ngIf="dataset && experiment" class="table text-offwhite"> + <thead> + <tr> + <th>Naziv</th> + <th *ngFor="let colInfo of dataset.columnInfo; let i = index"> + #{{i + 1}} {{colInfo.columnName}} + <input type="checkbox" class="btn-primary" checked (click)="changeInputColumns($event, colInfo.columnName)"> + </th> + </tr> + </thead> + <tbody> + <tr> + <th>Tip</th> + <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> + <mat-form-field> + <select matNativeControl class="form-control btn-primary" (change)="changeColumnType($event, i)"> + <option [selected]="!colInfo.isNumber" value="Kategorijski">Kategorijski</option> + <option [selected]="colInfo.isNumber" value="Numerički">Numerički</option> + </select> + </mat-form-field> + </td> + </tr> + <tr> + <th>Grafik</th> + <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> + <app-box-plot *ngIf="colInfo.isNumber"></app-box-plot> + <!--TODO: dodati [data]--> + <app-pie-chart *ngIf="!colInfo.isNumber"></app-pie-chart> + </td> + </tr> + <tr> + <th>Statistika</th> + <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> + <span *ngIf="colInfo.isNumber"> + Mean: {{colInfo.mean}}<br> + Median: {{colInfo.median}}<br> + Min: {{colInfo.min}}<br> + Max: {{colInfo.max}}<br> + <!-- TODO na ML-u: Q1 i Q3 u statistici + Q1: {{colInfo.q1}}<br> + Q3: {{colInfo.q3}}<br> + --> + </span> + <span *ngIf="!colInfo.isNumber"> + <span *ngFor="let uniqueValue of colInfo.uniqueValues | slice:0:5; let i = index"> + {{uniqueValue}}<br><!-- TODO na ML-u: broj ponavljanja unique values-a u zagradi nek pise --> + </span> + </span> + </td> + </tr> + <tr> + <th (click)="openEncodingDialog()">Enkoding + <span class="material-icons-round">settings</span> + </th> + <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> + <mat-form-field> + <select matNativeControl class="form-control btn-primary" [(ngModel)]="experiment.encodings[i].encoding"> + <option + *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" + [value]="option"> + {{ optionName }} + </option> + </select> + </mat-form-field> + </td> + </tr> + <tr> + <th (click)="openMissingValuesDialog()">Regulisanje nedostajućih vrednosti + <span class="material-icons-round">settings</span> + </th> + <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> + <!-- + <mat-form-field appearance="fill"> + <mat-select matNativeControl> + <mat-option [value]="NullValueOptions.DeleteColumns">Obriši kolonu</mat-option> + <mat-option [value]="NullValueOptions.DeleteRows">Obriši redove</mat-option> + <mat-option>Popuni sa _____ + <mat-select matNativeControl> + <mat-option>a</mat-option> + <mat-option>b</mat-option> + <mat-option>c</mat-option> + </mat-select> + </mat-option> + </mat-select> + </mat-form-field> + --> + <button mat-button [matMenuTriggerFor]="animals">Izabrana opcija</button> + <mat-menu #animals="matMenu"> + <button mat-menu-item>Obriši kolonu</button> + <button mat-menu-item>Obriši redove</button> + <button mat-menu-item [matMenuTriggerFor]="fillWith">Popuni sa ____</button> + </mat-menu> + + <mat-menu #fillWith="matMenu"> + <button mat-menu-item [matMenuTriggerFor]="replaceWith">Unesi vrednost...</button> + </mat-menu> + + <mat-menu #replaceWith="matMenu"> + <input type="text" mat-menu-item placeholder="Unesi vrednost..."> + </mat-menu> + </td> + </tr> + </tbody> +</table>
\ 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 f8c5f5f3..18e38203 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,10 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, Input, OnInit } from '@angular/core'; +import Dataset from 'src/app/_data/Dataset'; +import Experiment, { ColumnEncoding, Encoding, NullValReplacer, NullValueOptions } from 'src/app/_data/Experiment'; +import { DatasetsService } from 'src/app/_services/datasets.service'; +import { EncodingDialogComponent } from 'src/app/_modals/encoding-dialog/encoding-dialog.component'; +import { MatDialog } from '@angular/material/dialog'; +import { MissingvaluesDialogComponent } from 'src/app/_modals/missingvalues-dialog/missingvalues-dialog.component'; @Component({ selector: 'app-column-table', @@ -7,9 +13,109 @@ import { Component, OnInit } from '@angular/core'; }) export class ColumnTableComponent implements OnInit { - constructor() { } + @Input() dataset?: Dataset; + @Input() experiment?: Experiment; + + Object = Object; + Encoding = Encoding; + NullValueOptions = NullValueOptions; + + constructor(private datasetService: DatasetsService, public dialog: MatDialog) { + //ovo mi nece trebati jer primam dataset iz druge komponente + this.datasetService.getMyDatasets().subscribe((datasets) => { + this.dataset = datasets[0]; + //console.log(this.dataset); + this.experiment = new Experiment(); + for (let i = 0; i < this.dataset?.columnInfo.length; i++) { + this.experiment?.inputColumns.push(this.dataset.columnInfo[i].columnName); + } + this.resetColumnEncodings(Encoding.Label); + }); + } ngOnInit(): void { } + changeInputColumns(target: any, columnName: string) { + if (this.experiment != undefined) { + if (target.currentTarget.checked) { + if (this.experiment.inputColumns.filter(x => x == columnName)[0] == undefined) { + this.experiment.inputColumns.push(columnName); + } + } + else { + this.experiment.inputColumns = this.experiment.inputColumns.filter(x => x != columnName); + //console.log("Input columns: ", this.experiment.inputColumns); + //TODO: da se zatamni kolona koja je unchecked + } + } + } + + changeColumnType(target: any, indexOfCol: number) { + if (this.dataset != undefined) { + if (target.currentTarget.value == "Numerički") { + this.dataset.columnInfo[indexOfCol].isNumber = true; + } + else { + this.dataset.columnInfo[indexOfCol].isNumber = false; + } + } + } + + resetColumnEncodings(encodingType: Encoding) { + if (this.experiment != undefined && this.dataset != undefined) { + this.experiment.encodings = []; + 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); + } + } + } + openEncodingDialog() { + const dialogRef = this.dialog.open(EncodingDialogComponent, { + width: '300px' + }); + dialogRef.afterClosed().subscribe(selectedEncoding => { + if (selectedEncoding != undefined) + this.resetColumnEncodings(selectedEncoding); + }); + } + + resetMissingValuesTreatment(selectedMissingValuesOption: NullValueOptions) { + if (this.experiment != undefined && this.dataset != undefined) { + + if (selectedMissingValuesOption == NullValueOptions.DeleteColumns) { + this.experiment.nullValues = NullValueOptions.DeleteColumns; + this.experiment.nullValuesReplacers = []; + for (let i = 0; i < this.experiment.inputColumns.length; i++) { + this.experiment.nullValuesReplacers.push({ + column: this.experiment.inputColumns[i], + option: NullValueOptions.DeleteColumns, + value: "" + }); + } + } + else if (selectedMissingValuesOption == NullValueOptions.DeleteRows) { + this.experiment.nullValues = NullValueOptions.DeleteRows; + this.experiment.nullValuesReplacers = []; + for (let i = 0; i < this.experiment.inputColumns.length; i++) { + this.experiment.nullValuesReplacers.push({ + column: this.experiment.inputColumns[i], + option: NullValueOptions.DeleteRows, + value: "" + }); + } + } + + } + } + openMissingValuesDialog() { + const dialogRef = this.dialog.open(MissingvaluesDialogComponent, { + width: '400px' + }); + dialogRef.afterClosed().subscribe(selectedMissingValuesOption => { + if (selectedMissingValuesOption != undefined) + this.resetMissingValuesTreatment(selectedMissingValuesOption); + }); + } } diff --git a/frontend/src/app/_elements/metric-view/metric-view.component.html b/frontend/src/app/_elements/metric-view/metric-view.component.html index e7a4c547..3a6cce8d 100644 --- a/frontend/src/app/_elements/metric-view/metric-view.component.html +++ b/frontend/src/app/_elements/metric-view/metric-view.component.html @@ -1,5 +1,3 @@ <div> - <app-line-chart> - </app-line-chart> </div>
\ No newline at end of file diff --git a/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.css b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.css new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.css diff --git a/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html new file mode 100644 index 00000000..8898a4e4 --- /dev/null +++ b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html @@ -0,0 +1,16 @@ +<h1 mat-dialog-title>Enkodiranje svih kolona</h1> +<div mat-dialog-content> + <p>Odaberite tip enkodinga za sve kolone zajedno:</p> + <select matNativeControl class="form-control btn-primary" [(ngModel)]="selectedEncodingType"> + <option + *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" + [value]="option"> + {{ optionName }} + </option> + </select> + <p>Da li ste sigurni u izbor?</p> +</div> +<div mat-dialog-actions> + <button mat-button [mat-dialog-close]="selectedEncodingType" cdkFocusInitial>Da</button> + <button mat-button (click)="onNoClick()">Odustani</button> +</div>
\ No newline at end of file diff --git a/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.spec.ts b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.spec.ts new file mode 100644 index 00000000..77f30ae3 --- /dev/null +++ b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EncodingDialogComponent } from './encoding-dialog.component'; + +describe('EncodingDialogComponent', () => { + let component: EncodingDialogComponent; + let fixture: ComponentFixture<EncodingDialogComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ EncodingDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(EncodingDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.ts b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.ts new file mode 100644 index 00000000..3b7560bf --- /dev/null +++ b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit } from '@angular/core'; +import { MatDialogRef } from '@angular/material/dialog'; +import { Encoding } from 'src/app/_data/Experiment'; + + +@Component({ + selector: 'app-encoding-dialog', + templateUrl: './encoding-dialog.component.html', + styleUrls: ['./encoding-dialog.component.css'] +}) +export class EncodingDialogComponent implements OnInit { + + selectedEncodingType?: Encoding; + Encoding = Encoding; + Object = Object; + + constructor(public dialogRef: MatDialogRef<EncodingDialogComponent>) + { + this.selectedEncodingType = Encoding.Label; + } + + ngOnInit(): void { + } + + onNoClick() { + this.dialogRef.close(); + } +} diff --git a/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css diff --git a/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.html b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.html new file mode 100644 index 00000000..81aec5f8 --- /dev/null +++ b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.html @@ -0,0 +1,13 @@ +<h1 mat-dialog-title>Popunjavanje nedostajućih vrednosti</h1> +<div mat-dialog-content> + <p>Želim da:</p> + <mat-radio-group [(ngModel)]="selectedMissingValuesOption"> + <mat-radio-button [value]="NullValueOptions.DeleteColumns" checked>obrišem sve kolone koje sadrže nedostajuće vrednosti</mat-radio-button> + <mat-radio-button [value]="NullValueOptions.DeleteRows">obrišem sve redove koji sadrže nedostajuće vrednosti</mat-radio-button> + </mat-radio-group> + <p>Da li ste sigurni u izbor?</p> +</div> +<div mat-dialog-actions> + <button mat-button [mat-dialog-close]="selectedMissingValuesOption" cdkFocusInitial>Da</button> + <button mat-button (click)="onNoClick()">Odustani</button> +</div>
\ No newline at end of file diff --git a/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.spec.ts b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.spec.ts new file mode 100644 index 00000000..958925f4 --- /dev/null +++ b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MissingvaluesDialogComponent } from './missingvalues-dialog.component'; + +describe('MissingvaluesDialogComponent', () => { + let component: MissingvaluesDialogComponent; + let fixture: ComponentFixture<MissingvaluesDialogComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ MissingvaluesDialogComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(MissingvaluesDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.ts b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.ts new file mode 100644 index 00000000..908edd9e --- /dev/null +++ b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit } from '@angular/core'; +import { MatDialogRef } from '@angular/material/dialog'; +import { NullValueOptions } from 'src/app/_data/Experiment'; + +@Component({ + selector: 'app-missingvalues-dialog', + templateUrl: './missingvalues-dialog.component.html', + styleUrls: ['./missingvalues-dialog.component.css'] +}) +export class MissingvaluesDialogComponent implements OnInit { + + selectedMissingValuesOption?: NullValueOptions; + + NullValueOptions = NullValueOptions; + + constructor(public dialogRef: MatDialogRef<MissingvaluesDialogComponent>) + { + this.selectedMissingValuesOption = NullValueOptions.DeleteColumns; + } + + ngOnInit(): void { + } + + onNoClick() { + this.dialogRef.close(); + } + +} diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index cd742cfc..30cf2ea8 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -7,13 +7,15 @@ import { ProfileComponent } from './_pages/profile/profile.component'; import { PlaygroundComponent } from './_pages/playground/playground.component'; import { ExperimentComponent } from './_pages/experiment/experiment.component'; import { ArchiveComponent } from './_pages/archive/archive.component'; +import { ColumnTableComponent } from './_elements/column-table/column-table.component'; const routes: Routes = [ { path: '', component: HomeComponent, data: { title: 'Početna strana' } }, { path: 'experiment', component: ExperimentComponent, data: { title: 'Eksperiment' } }, { path: 'archive', component: ArchiveComponent, data: { title: 'Arhiva' } }, { path: 'profile', component: ProfileComponent, canActivate: [AuthGuardService], data: { title: 'Profil' } }, - { path: 'playground', component: PlaygroundComponent, data: { title: 'Zabava' } } + { path: 'playground', component: PlaygroundComponent, data: { title: 'Zabava' } }, + { path: 'sonja', component: ColumnTableComponent } ]; @NgModule({ diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index da81fc4a..70e78394 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -19,6 +19,8 @@ import { LoginModalComponent } from './_modals/login-modal/login-modal.component import { RegisterModalComponent } from './_modals/register-modal/register-modal.component'; import { AlertDialogComponent } from './_modals/alert-dialog/alert-dialog.component'; import { YesNoDialogComponent } from './_modals/yes-no-dialog/yes-no-dialog.component'; +import { EncodingDialogComponent } from './_modals/encoding-dialog/encoding-dialog.component'; +import { MissingvaluesDialogComponent } from './_modals/missingvalues-dialog/missingvalues-dialog.component'; // Pages import { HomeComponent } from './_pages/home/home.component'; import { ProfileComponent } from './_pages/profile/profile.component'; @@ -74,7 +76,9 @@ export function initializeApp(appConfig: Configuration) { ColumnTableComponent, PieChartComponent, BoxPlotComponent, - FolderComponent + FolderComponent, + EncodingDialogComponent, + MissingvaluesDialogComponent ], imports: [ BrowserModule, diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 1100222e..e65d8d7c 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -3,4 +3,5 @@ @import './styles/layout.css'; @import './styles/helper.css'; @import './styles/scrollbar.css'; -@import './styles/fx.css';
\ No newline at end of file +@import './styles/fx.css'; +@import 'material-icons/iconfont/material-icons.css';
\ No newline at end of file |