diff options
Diffstat (limited to 'frontend/src/app/_elements/column-table')
3 files changed, 337 insertions, 139 deletions
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 f40a3aff..4dfb32ee 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.css +++ b/frontend/src/app/_elements/column-table/column-table.component.css @@ -44,7 +44,6 @@ table.fixed th:first-child { mat-slider { width: 150px; - } .belowColumn { @@ -65,13 +64,13 @@ mat-slider { border-style: solid; border-width: 0px 1px 1px 1px; } + #footer { display: flex; flex-direction: row; justify-content: center; } - #missingValuesHeader { font-size: 12px; line-height: 110% !important; @@ -119,3 +118,87 @@ table ::ng-deep .mat-form-field-wrapper { .graphic-class { background-color: white !important; } + + +/* TABS STYLE */ + +#folder-table { + border: 1px solid var(--ns-primary); + border-radius: 4px; +} + +#tabs { + display: flex; + flex-direction: row; + align-items: flex-end; + height: 3.2rem; +} + +#tabs>.folder-tab:not(:first-child) { + margin-left: -5px; +} + +.folder-tab-end { + margin-left: auto; + color: var(--offwhite) !important; + overflow: hidden; +} + +.folder-tab, +.folder-tab-end { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + position: relative; + overflow-x: hidden; + height: 2.5rem; + background-color: var(--ns-bg-dark-100); + border-color: var(--ns-primary); + color: var(--ns-primary); + border-style: solid; + border-width: 1px 1px 0 1px; +} + +.folder-tab:not(:first-child) { + margin-block-start: auto; +} + +.folder-tab { + display: flex; + flex-direction: row; + justify-content: space-between; +} + +.selected-tab { + height: 3rem; + background-color: var(--ns-primary); + color: var(--offwhite); +} + +.hover-tab { + height: 3.2rem; +} + +.selected-tab, +.hover-tab { + width: fit-content !important; +} + +.tab-link { + color: var(--offwhite) !important; + text-decoration: none !important; + cursor: pointer; +} + +.tab-link:active { + text-decoration: underline !important; +} + +.selected-tab { + background-color: var(--ns-primary); +} + +.hidden { + display: none; +}
\ 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 56b95c29..5f4412a1 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.html +++ b/frontend/src/app/_elements/column-table/column-table.component.html @@ -1,38 +1,102 @@ -<table *ngIf="dataset && experiment" class="table text-offwhite fixed bg-blur"> - <thead> - <tr> - <th>Naziv</th> - <th class="columnNames" *ngFor="let colInfo of dataset.columnInfo; let i = index"> - <div class="cell-align"> - #{{i + 1}} {{colInfo.columnName}} - <mat-checkbox checked (change)="changeInputColumns($event, colInfo.columnName)"></mat-checkbox> - </div> - </th> - </tr> - </thead> - <tbody> - <tr> - <th>Tip</th> - <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> - <mat-form-field> - <mat-select matNativeControl [(value)]="colInfo.isNumber"> - <mat-option [value]="false">Kategorijski</mat-option> - <mat-option [value]="true">Numerički</mat-option> - </mat-select> - </mat-form-field> - </td> - </tr> - <tr class="graphics-row"> - <th class="no-pad border-bottom">Grafik</th> - <td class="graphic-class no-pad" *ngFor="let colInfo of dataset.columnInfo; let i = index"> - <app-box-plot *ngIf="colInfo.isNumber" [width]="150" [height]="150"></app-box-plot> - <app-pie-chart *ngIf="!colInfo.isNumber" [width]="150" [height]="150"></app-pie-chart> - </td> - </tr> - <tr> - <th class="brighter">Statistika</th> - <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> - <span *ngIf="colInfo.isNumber"> +<div id="tabs"> + <div class="folder-tab p-1 rounded-top" *ngFor="let tab of tabs; let i = index" [style]="'z-index:' + calcZIndex(i) + ' ;'" [ngClass]="{'selected-tab' : selectedTab.index == i, 'hover-tab' : hoveringOverTab?.index == i}"> + <a class="m-1 stretched-link tab-link" (click)="selectTab(i)" (mouseenter)="hoverOverTab(i)" (mouseleave)="hoverOverTab(-1)"> + {{tab.name}} + </a> + </div> + <button mat-button class="p-1 folder-tab-end rounded-top"> + Kolone + <mat-icon>keyboard_double_arrow_down</mat-icon> + <!--meni ovde--> + </button> +</div> +<div id="folder-table" *ngIf="dataset && experiment"> + <!--<div [ngSwitch]="tabToDisplay">--> + <div> + + <div [ngClass]="{'hidden': tabToDisplay != Table.Data}"> + <table class="table text-offwhite fixed bg-blur"> + <thead> + <tr> + <th>#</th> + <th class="columnNames" *ngFor="let colInfo of dataset.columnInfo; let i = index"> + #{{i + 1}} {{colInfo.columnName}} + <mat-checkbox checked (change)="changeInputColumns($event, colInfo.columnName)"></mat-checkbox> + </th> + </tr> + </thead> + <tbody> + <tr *ngFor="let row of tableData; let i = index"> + <th>#{{i}}</th> + <td *ngFor="let col of row; let j = index"> + <div class="text-overflow"> + {{col}} + </div> + </td> + </tr> + </tbody> + </table> + </div> + + <div [ngClass]="{'hidden': tabToDisplay != Table.CorrelationMatrix}"> + <table class="table text-offwhite fixed bg-blur"> + <thead> + <tr> + <th>Naziv</th> + <th class="columnNames" *ngFor="let colInfo of dataset.columnInfo; let i = index"> + #{{i + 1}} {{colInfo.columnName}} + </th> + </tr> + </thead> + <tbody> + <tr *ngFor="let colInfo of dataset.columnInfo; let i = index"> + <th>#{{i + 1}} {{colInfo.columnName}}</th> + <td *ngFor="let colInfo of dataset.columnInfo; let j = index"> + <div class="text-overflow"> + 0.1 + </div> + </td> + </tr> + </tbody> + </table> + </div> + + <div [ngClass]="{'hidden': tabToDisplay != Table.Columns}"> + <table class="table text-offwhite fixed bg-blur"> + <thead> + <tr> + <th>Naziv</th> + <th class="columnNames" *ngFor="let colInfo of dataset.columnInfo; let i = index"> + <div class="cell-align"> + #{{i + 1}} {{colInfo.columnName}} + <mat-checkbox checked (change)="changeInputColumns($event, colInfo.columnName)"></mat-checkbox> + </div> + </th> + </tr> + </thead> + <tbody> + <tr> + <th>Tip</th> + <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> + <mat-form-field> + <mat-select matNativeControl [(value)]="colInfo.isNumber"> + <mat-option [value]="false">Kategorijski</mat-option> + <mat-option [value]="true">Numerički</mat-option> + </mat-select> + </mat-form-field> + </td> + </tr> + <tr class="graphics-row"> + <th class="no-pad border-bottom">Grafik</th> + <td class="graphic-class no-pad" *ngFor="let colInfo of dataset.columnInfo; let i = index"> + <app-box-plot *ngIf="colInfo.isNumber" [width]="150" [height]="150"></app-box-plot> + <app-pie-chart *ngIf="!colInfo.isNumber" [width]="150" [height]="150"></app-pie-chart> + </td> + </tr> + <tr> + <th class="brighter">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> @@ -42,119 +106,122 @@ Q3: {{colInfo.q3}}<br> --> </span> - <div class="text-overflow" *ngIf="!colInfo.isNumber"> - <span *ngFor="let uniqueValue of colInfo.uniqueValues | slice:0:6; let i = index"> + <div class="text-overflow" *ngIf="!colInfo.isNumber"> + <span *ngFor="let uniqueValue of colInfo.uniqueValues | slice:0:6; let i = index"> {{uniqueValue}}<br><!-- TODO na ML-u: broj ponavljanja unique values-a u zagradi nek pise --> </span> - </div> - </td> - </tr> - <tr style="padding: 0"> - <th class="brighter cell-align" (click)="openEncodingDialog()"> - <span class="verticalAlign">Enkodiranje</span> - <span class="material-icons-round verticalAlign">settings</span> - </th> - <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> - <mat-form-field> - <mat-select matNativeControl [(value)]="experiment.encodings[i].encoding"> - <mat-option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" [value]="option"> - {{ optionName }} - </mat-option> - </mat-select> - </mat-form-field> - </td> - </tr> - <tr> - <th class="brighter cell-align" (click)="openMissingValuesDialog()"> - <div id="missingValuesHeader">Regulisanje<br>nedostajućih<br>vrednosti<br></div> - <span class="material-icons-round">settings</span> - </th> - <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> - - <button class="w-100" mat-raised-button [matMenuTriggerFor]="menu" id="main_{{colInfo.columnName}}" #nullValMenu> + </div> + </td> + </tr> + <tr style="padding: 0"> + <th class="brighter cell-align" (click)="openEncodingDialog()"> + <span class="verticalAlign">Enkodiranje</span> + <span class="material-icons-round verticalAlign">settings</span> + </th> + <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> + <mat-form-field> + <mat-select matNativeControl [(value)]="experiment.encodings[i].encoding"> + <mat-option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" [value]="option"> + {{ optionName }} + </mat-option> + </mat-select> + </mat-form-field> + </td> + </tr> + <tr> + <th class="brighter cell-align" (click)="openMissingValuesDialog()"> + <div id="missingValuesHeader">Regulisanje<br>nedostajućih<br>vrednosti<br></div> + <span class="material-icons-round">settings</span> + </th> + <td *ngFor="let colInfo of dataset.columnInfo; let i = index"> + + <button class="w-100" mat-raised-button [matMenuTriggerFor]="menu" id="main_{{colInfo.columnName}}" #nullValMenu> <div class="cell-align"> {{nullValOption[i]}} <mat-icon>arrow_drop_down</mat-icon> </div> </button> - <mat-menu #menu="matMenu"> - <button mat-menu-item (click)="MissValsDeleteClicked($event, NullValueOptions.DeleteColumns, i)" value={{colInfo.columnName}}>Obriši kolonu</button> - <button mat-menu-item (click)="MissValsDeleteClicked($event, NullValueOptions.DeleteRows, i)" value={{colInfo.columnName}}>Obriši redove</button> - <button mat-menu-item [matMenuTriggerFor]="fillWith">Popuni sa ____</button> - </mat-menu> + <mat-menu #menu="matMenu"> + <button mat-menu-item (click)="MissValsDeleteClicked($event, NullValueOptions.DeleteColumns, i)" value={{colInfo.columnName}}>Obriši kolonu</button> + <button mat-menu-item (click)="MissValsDeleteClicked($event, NullValueOptions.DeleteRows, i)" value={{colInfo.columnName}}>Obriši redove</button> + <button mat-menu-item [matMenuTriggerFor]="fillWith">Popuni sa ____</button> + </mat-menu> - <mat-menu #fillWith="matMenu"> - <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.mean}}>Mean ({{colInfo.mean}})</button> - <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.median}}>Median ({{colInfo.median}})</button> - <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.max}}>Max ({{colInfo.max}})</button> - <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.min}}>Min ({{colInfo.min}})</button> + <mat-menu #fillWith="matMenu"> + <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.mean}}>Mean ({{colInfo.mean}})</button> + <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.median}}>Median ({{colInfo.median}})</button> + <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.max}}>Max ({{colInfo.max}})</button> + <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.min}}>Min ({{colInfo.min}})</button> - <button *ngIf="!colInfo.isNumber" mat-menu-item [matMenuTriggerFor]="uniques">Najčešće vrednosti</button> + <button *ngIf="!colInfo.isNumber" mat-menu-item [matMenuTriggerFor]="uniques">Najčešće vrednosti</button> - <button mat-menu-item [matMenuTriggerFor]="replaceWith">Unesi vrednost...</button> - </mat-menu> + <button mat-menu-item [matMenuTriggerFor]="replaceWith">Unesi vrednost...</button> + </mat-menu> - <mat-menu #uniques="matMenu"> - <button mat-menu-item *ngFor="let uniqueValue of colInfo.uniqueValues" (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{uniqueValue}}>{{uniqueValue}}</button> - </mat-menu> + <mat-menu #uniques="matMenu"> + <button mat-menu-item *ngFor="let uniqueValue of colInfo.uniqueValues" (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{uniqueValue}}>{{uniqueValue}}</button> + </mat-menu> - <mat-menu #replaceWith="matMenu"> - <input type="text" id={{colInfo.columnName}} mat-menu-item placeholder="Unesi vrednost..." [value]> - <button [disabled]="getValue(colInfo.columnName) == ''" mat-menu-item value={{getValue(colInfo.columnName)}} (click)="MissValsReplaceClicked($event, colInfo.columnName, i)">Potvrdi unos</button> - </mat-menu> + <mat-menu #replaceWith="matMenu"> + <input type="text" id={{colInfo.columnName}} mat-menu-item placeholder="Unesi vrednost..." [value]> + <button [disabled]="getValue(colInfo.columnName) == ''" mat-menu-item value={{getValue(colInfo.columnName)}} (click)="MissValsReplaceClicked($event, colInfo.columnName, i)">Potvrdi unos</button> + </mat-menu> - </td> - </tr> - <tr class="row-height" *ngFor="let row of tableData; let i = index"> - <th *ngIf="i == 0" [attr.rowspan]="tableData!.length">Vrednosti</th> + </td> + </tr> + <!--<tr class="row-height" *ngFor="let row of tableData; let i = index"> + <th *ngIf="i == 0" [attr.rowspan]="tableData!.length">Vrednosti</th> - <td class="text-center" *ngFor="let col of row; let j = index"> - <div class="text-overflow"> - {{col}} - </div> - </td> - </tr> - </tbody> -</table> + <td class="text-center" *ngFor="let col of row; let j = index"> + <div class="text-overflow"> + {{col}} + </div> + </td> + </tr>--> + </tbody> + </table> + </div> + </div> +</div> <div class="container-fluid text-offwhite belowColumn"> <div class="row "> <div class="col-sm-3 slider rounded" style="border:1px solid var(--ns-primary)"> - - <div class="text-center pt-3 pb-0 mb-0"><b>{{testSetDistribution}}%</b> : <b>{{100-testSetDistribution}}%</b></div> - <div class="text-center pt-0 mt-0">Trening + + <div class="text-center pt-3 pb-0 mb-0"><b>{{testSetDistribution}}%</b> : <b>{{100-testSetDistribution}}%</b></div> + <div class="text-center pt-0 mt-0">Trening <mat-slider min="10" max="90" step="10" [(ngModel)]="testSetDistribution" (input)="updateTestSet($event)"></mat-slider> Test</div> - + </div> <div class="col-sm-3 slider rounded" style="border:1px solid var(--ns-primary);margin-left: 10px;"> <div class="text-center text-offwhite justify-content-center align-items-center"> - <mat-checkbox class="pt-4" color="accent" >Nasumicni redosled podataka</mat-checkbox> + <mat-checkbox class="pt-4" color="accent">Nasumicni redosled podataka</mat-checkbox> </div> </div> <div class="col-sm-2 rounded"> - - <mat-form-field appearance="fill" class="align-items-center justify-content-center pt-3 w-100"> - <mat-label>Tip problema</mat-label> - <mat-select value="ToDo1"> - <mat-option value="ToDo1">Regresioni</mat-option> - <mat-option value="ToDo2">Binarni-Klasifikacioni</mat-option> - <mat-option value="ToDo3">Multi-Klasifikacioni</mat-option> - </mat-select> - </mat-form-field> - + + <mat-form-field appearance="fill" class="align-items-center justify-content-center pt-3 w-100"> + <mat-label>Tip problema</mat-label> + <mat-select value="ToDo1"> + <mat-option value="ToDo1">Regresioni</mat-option> + <mat-option value="ToDo2">Binarni-Klasifikacioni</mat-option> + <mat-option value="ToDo3">Multi-Klasifikacioni</mat-option> + </mat-select> + </mat-form-field> + </div> <div class="col-sm-2 rounded"> - - <mat-form-field appearance="fill" class="align-items-center justify-content-center pt-3 w-100"> - <mat-label>Izlazna kolona</mat-label> - <mat-select> - <mat-option *ngFor="let item of dataset?.columnInfo" [value]="item.columnName">{{item.columnName}}</mat-option> - </mat-select> - </mat-form-field> - + + <mat-form-field appearance="fill" class="align-items-center justify-content-center pt-3 w-100"> + <mat-label>Izlazna kolona</mat-label> + <mat-select> + <mat-option *ngFor="let item of dataset?.columnInfo" [value]="item.columnName">{{item.columnName}}</mat-option> + </mat-select> + </mat-form-field> + </div> <div class="col-sm-1 d-flex align-items-center justify-content-center"> <button mat-button (click)="ok()" class="bottom-button text-offwhite rounded-bottom"> @@ -168,6 +235,4 @@ </button> </div> </div> -</div> - - +</div>
\ 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 c48bf869..137c383c 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.ts +++ b/frontend/src/app/_elements/column-table/column-table.component.ts @@ -26,8 +26,8 @@ export class ColumnTableComponent implements AfterViewInit { tableData?: any[][]; nullValOption: string[] = []; - testSetDistribution:number=70; - constructor(private datasetService: DatasetsService, public csvParseService: CsvParseService, public dialog: MatDialog) { + testSetDistribution: number = 70; + constructor(private datasetService: DatasetsService, public csvParseService: CsvParseService, public dialog: MatDialog) { //ovo mi nece trebati jer primam dataset iz druge komponente } @@ -92,13 +92,13 @@ export class ColumnTableComponent implements AfterViewInit { } } openEncodingDialog() { - const dialogRef = this.dialog.open(EncodingDialogComponent, { - width: '300px' - }); - dialogRef.afterClosed().subscribe(selectedEncoding => { - if (selectedEncoding != undefined) - this.resetColumnEncodings(selectedEncoding); - }); + const dialogRef = this.dialog.open(EncodingDialogComponent, { + width: '300px' + }); + dialogRef.afterClosed().subscribe(selectedEncoding => { + if (selectedEncoding != undefined) + this.resetColumnEncodings(selectedEncoding); + }); } resetMissingValuesTreatment(selectedMissingValuesOption: NullValueOptions) { @@ -115,7 +115,7 @@ export class ColumnTableComponent implements AfterViewInit { }); this.nullValOption[i] = "Obriši kolonu"; } - } + } else if (selectedMissingValuesOption == NullValueOptions.DeleteRows) { this.experiment.nullValues = NullValueOptions.DeleteRows; this.experiment.nullValuesReplacers = []; @@ -135,12 +135,12 @@ export class ColumnTableComponent implements AfterViewInit { width: '400px' }); dialogRef.afterClosed().subscribe(selectedMissingValuesOption => { - if (selectedMissingValuesOption != undefined) + if (selectedMissingValuesOption != undefined) this.resetMissingValuesTreatment(selectedMissingValuesOption); }); } - updateTestSet(event:MatSliderChange){ - this.testSetDistribution=event.value!; + updateTestSet(event: MatSliderChange) { + this.testSetDistribution = event.value!; } @@ -160,7 +160,7 @@ export class ColumnTableComponent implements AfterViewInit { arrayElement.option = (replacementType == NullValueOptions.DeleteColumns) ? NullValueOptions.DeleteColumns : NullValueOptions.DeleteRows; arrayElement.value = ""; } - + this.nullValOption[index] = (replacementType == NullValueOptions.DeleteColumns) ? "Obriši kolonu" : "Obriši redove"; } } @@ -169,7 +169,7 @@ export class ColumnTableComponent implements AfterViewInit { if (this.experiment != undefined) { let fillValue = (<HTMLInputElement>event.currentTarget).value; let arrayElement = this.experiment.nullValuesReplacers.filter(x => x.column == columnName)[0]; - + if (arrayElement == undefined) { this.experiment.nullValuesReplacers.push({ column: columnName, @@ -195,4 +195,54 @@ export class ColumnTableComponent implements AfterViewInit { } -} + tabs = [ + new Tab(0, 'Podešavanja kolona', Table.Columns), + new Tab(1, 'Podaci', Table.Data), + new Tab(2, 'Korelaciona matrica', Table.CorrelationMatrix) + ] + + selectedTab: Tab = this.tabs[0]; + hoveringOverTab: (Tab | null) = null; + + tabToDisplay: Table = Table.Columns; + + selectTab(index: number) { + this.selectedTab = this.tabs[index]; + this.tabToDisplay = this.tabs[index].value; + } + + hoverOverTab(index: number) { + if (index < 0) { + this.hoveringOverTab = null; + this.tabToDisplay = this.selectedTab.value; + } else { + this.hoveringOverTab = this.tabs[index]; + this.tabToDisplay = this.tabs[index].value; + } + } + + calcZIndex(i: number) { + let zIndex = (this.tabs.length - i - 1) + if (this.selectedTab.index == i) + zIndex = this.tabs.length + 1; + if (this.hoveringOverTab?.index == i) + zIndex = this.tabs.length + 2; + return zIndex; + } + + Table = Table; +} + +export enum Table { + Columns, + Data, + CorrelationMatrix +} + +export class Tab { + constructor( + public index: number, + public name: string, + public value: Table + ) { } +} |