diff options
Diffstat (limited to 'frontend/src')
15 files changed, 623 insertions, 229 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 1e7d4745..4dfb32ee 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.css +++ b/frontend/src/app/_elements/column-table/column-table.component.css @@ -43,15 +43,32 @@ table.fixed th:first-child { } mat-slider { - width: 300px; + width: 150px; } .belowColumn { - background-color: var(--ns-bg-dark-50); + background-color: transparent; } .slider { - background-color: var(--ns-bg-dark-100); + background-color: var(--ns-bg-dark-50); +} + +.bottom-button { + font-size: large; + position: relative; + background-color: var(--ns-primary); + width: 10rem; + height: 2.3rem; + border-color: var(--ns-primary); + border-style: solid; + border-width: 0px 1px 1px 1px; +} + +#footer { + display: flex; + flex-direction: row; + justify-content: center; } #missingValuesHeader { @@ -100,4 +117,88 @@ 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 92a4699a..0c33786e 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,93 +106,105 @@ 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> - -<div class="container text-offwhite belowColumn"> - <div class="row "> - <div class="col-sm slider rounded"> + <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="ns-row"> + <div class="ns-col 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 - <mat-slider min="10" max="90" step="10" [(ngModel)]="testSetDistribution" (input)="updateTestSet($event)"></mat-slider>Test</div> + <mat-slider min="10" max="90" step="10" [(ngModel)]="testSetDistribution" (input)="updateTestSet($event)"></mat-slider> + Test</div> </div> + <div class="ns-col 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">Nasumični redosled podataka</mat-checkbox> + </div> + </div> + + <div class="break-2"></div> - <div class="col-sm-3 d-flex pt-3"> - <mat-form-field appearance="fill" style="width: 270px;"> + <div class="ns-col 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> @@ -137,15 +213,25 @@ </mat-select> </mat-form-field> </div> - <div class="col-sm-3 d-flex pt-3"> - <mat-form-field appearance="fill"> + <div class="ns-col 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> </div> - + <div class="break-1"></div> + <div class="ns-col d-flex align-items-center justify-content-center"> + <button mat-button (click)="ok()" class="bottom-button text-offwhite rounded-bottom"> + <div class="f-row" style="justify-content: space-around;"> + <div>Potvrdi</div> + <div class="icon-double pt-1"> + <mat-icon>check</mat-icon> + <mat-icon>check</mat-icon> + </div> + </div> + </button> + </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 85046b8c..137c383c 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, Input, OnInit, ViewChildren } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChildren } 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'; @@ -19,15 +19,15 @@ export class ColumnTableComponent implements AfterViewInit { @Input() dataset?: Dataset; @Input() experiment?: Experiment; @ViewChildren("nullValMenu") nullValMenus!: ElementRef[]; - + @Output() okPressed: EventEmitter<string> = new EventEmitter(); Object = Object; Encoding = Encoding; NullValueOptions = NullValueOptions; 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, @@ -190,5 +190,59 @@ export class ColumnTableComponent implements AfterViewInit { return (<HTMLInputElement>document.getElementById(columnName)).value; return '0'; } + ok() { + this.okPressed.emit(); + } + + + 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 + ) { } +} diff --git a/frontend/src/app/_elements/datatable/datatable.component.html b/frontend/src/app/_elements/datatable/datatable.component.html index fe359db0..17a187ef 100644 --- a/frontend/src/app/_elements/datatable/datatable.component.html +++ b/frontend/src/app/_elements/datatable/datatable.component.html @@ -1,4 +1,4 @@ -<div *ngIf="tableData.hasInput"> +<div *ngIf="tableData.hasInput" class="position-relative"> <div class="text-white"> <div *ngIf="!tableData.loaded" style="width: 100%; height: 100%;" class="d-flex justify-content-center align-items-center"> <app-loading></app-loading> @@ -22,15 +22,9 @@ </tr> </tbody> </table> - <tfoot> - <tr> - <td colspan="100" class="fs-6"> - <div class="footer-center"> - <div>+ {{tableData.numRows - 11}} redova...</div> - </div> - </td> - </tr> - </tfoot> + </div> + <div class="footer-center" > + <div>+ {{tableData.numRows - 11}} redova...</div> </div> </div> </div> diff --git a/frontend/src/app/_elements/folder/folder.component.css b/frontend/src/app/_elements/folder/folder.component.css index ce9b9fad..1ce4e6a3 100644 --- a/frontend/src/app/_elements/folder/folder.component.css +++ b/frontend/src/app/_elements/folder/folder.component.css @@ -64,6 +64,10 @@ background-color: var(--ns-primary); } +#search ::ng-deep .mat-form-field-wrapper { + margin-top: -2.1rem; +} + #searchbar { height: 2.5rem; background-color: var(--ns-bg-dark-100); @@ -158,7 +162,7 @@ .file-content { width: 100%; - height: 100%; + height: 92%; position: relative; } diff --git a/frontend/src/app/_elements/form-dataset/form-dataset.component.css b/frontend/src/app/_elements/form-dataset/form-dataset.component.css index 6b3e2bed..56eb3cef 100644 --- a/frontend/src/app/_elements/form-dataset/form-dataset.component.css +++ b/frontend/src/app/_elements/form-dataset/form-dataset.component.css @@ -1,19 +1,62 @@ .folderBox { width: 100%; - height: 100%; + height: 90%; position: relative; } +.file-container{ + border: 4px solid transparent; + position: relative; + margin-left: 3%; + margin-top: 3rem; + width: 94%; + min-height: 500px; +} +.fileButton{ + position: absolute; + margin-top: -3rem; + display: flex; + flex-direction: row; + align-items: center; +} +.fileButton label{ + margin-left: 10px; +} +.dottedClass +{ + border: 4px dotted white; + border-radius: 25px; +} + +.hidden{ + visibility: hidden; +} + +.file { + position: absolute; + width: 100%; + height: 100%; + opacity: 0; +} + +.file input{ + + border-radius: 4px; + margin-top: -15px; + width: 100%; + height: 100%; +} + .icon-display { position: absolute; - top: 50%; + top: 45%; left: 50%; transform: translate(-50%, -50%) scale(4); } .bottomBar { position: absolute; - bottom: 0%; + bottom: -6%; left: 5%; } 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 50a33583..e0c7f288 100644 --- a/frontend/src/app/_elements/form-dataset/form-dataset.component.html +++ b/frontend/src/app/_elements/form-dataset/form-dataset.component.html @@ -1,12 +1,27 @@ <div class="folderBox"> - <mat-icon class="icon-display">upload</mat-icon> - <!-- - - <div class="px-5 mt-5"> - <app-datatable [tableData]="tableData"></app-datatable> + <div class="file-container" [ngClass]="{'dottedClass': !tableData.hasInput}"> + + <i class="material-icons-outlined icon-display" [ngClass]="{'hidden': tableData.hasInput}">file_upload</i> + + <div class="fileButton"> + <button type="button" mat-raised-button (click)="fileInput.click()">Choose File</button> + <label>{{filename}}</label> + </div> + + <input class="file" id="file-upload" (change)="changeListener($event)" #fileInput type="file" accept=".csv"> + + + <div class="mt-5 datatable"> + <app-datatable [tableData]="tableData"></app-datatable> + </div> + + </div> - --> + + + + <div class="bottomBar"> <div class="row"> @@ -27,8 +42,8 @@ </div> <div class="col-sm mb-3"> - <input id="fileInput" class="form-control btn-lg" type="file" class="upload" (change)="changeListener($event)" accept=".csv"> - + <!--<input id="fileInput" class="form-control btn-lg" type="file" class="upload" (change)="changeListener($event)" accept=".csv"> + --> </div> <div class="col-sm"> diff --git a/frontend/src/app/_elements/form-dataset/form-dataset.component.ts b/frontend/src/app/_elements/form-dataset/form-dataset.component.ts index 9bdd7e14..254f5fe4 100644 --- a/frontend/src/app/_elements/form-dataset/form-dataset.component.ts +++ b/frontend/src/app/_elements/form-dataset/form-dataset.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Output, ViewChild } from '@angular/core'; +import { Component, ElementRef, EventEmitter, Output, ViewChild } from '@angular/core'; import Dataset from 'src/app/_data/Dataset'; import { DatasetsService } from 'src/app/_services/datasets.service'; import { ModelsService } from 'src/app/_services/models.service'; @@ -29,9 +29,14 @@ export class FormDatasetComponent { tableData: TableData = new TableData(); + @ViewChild('fileInput') fileInput! : ElementRef + + filename: String; + constructor(private modelsService: ModelsService, private datasetsService: DatasetsService, private csv: CsvParseService) { this.dataset = new Dataset(); this.dataset.delimiter = ','; + this.filename = ""; } //@ViewChild('fileImportInput', { static: false }) fileImportInput: any; cemu je ovo sluzilo? @@ -45,6 +50,7 @@ export class FormDatasetComponent { else this.tableData.hasInput = true; + this.filename = this.files[0].name; this.tableData.loaded = false; this.update(); } diff --git a/frontend/src/app/_elements/form-model/form-model.component.css b/frontend/src/app/_elements/form-model/form-model.component.css index c0ae9365..5776085f 100644 --- a/frontend/src/app/_elements/form-model/form-model.component.css +++ b/frontend/src/app/_elements/form-model/form-model.component.css @@ -21,7 +21,7 @@ mat-form-field { hr { color: var(--offwhite) !important; margin-bottom: 30px; - ; + } .neuron { @@ -33,55 +33,19 @@ hr { background-color: var(--ns-bg-dark-100) !important; min-width: none; max-width: 12.5rem; -} -col-1 { - text-align: center; } -.row { - margin: 0; - padding: 0; -} -.ns-row { - width: 98%; - display: flex; - flex-direction: row; - flex-wrap: wrap; +.row { margin: 0; padding: 0; } -.ns-col { - flex-grow: 1; - padding: 2px; - margin-bottom: 0; - padding-bottom: 0; -} - ::ng-deep .mat-form-field-wrapper { margin-bottom: -1.85em; } -.break-1, -.break-2 { - height: 1px; - width: 100%; -} - -@media screen and (min-width: 1200px) { - .break-1 { - display: none; - } -} - -@media screen and (min-width: 2175px) { - .break-2 { - display: none; - } -} - #layers-control { display: flex; flex-direction: row; @@ -104,11 +68,14 @@ col-1 { border: 1px solid var(--ns-primary); border-radius: 4px; margin: 5px; - padding: 3px; + padding: 0px; width: 12rem; - height: 13rem; + height: 13.5rem; } .layer>mat-form-field { margin-left: 0; +} +.m-2{ + max-height: 20 rem; }
\ No newline at end of file diff --git a/frontend/src/app/_elements/form-model/form-model.component.html b/frontend/src/app/_elements/form-model/form-model.component.html index 396d40c6..33ec85de 100644 --- a/frontend/src/app/_elements/form-model/form-model.component.html +++ b/frontend/src/app/_elements/form-model/form-model.component.html @@ -15,7 +15,6 @@ {{ optionName }} </mat-option> </mat-select> - </mat-form-field> </div> @@ -93,7 +92,10 @@ <hr> <div class="m-2"> <app-graph [model]="newModel" [inputCols]="newModel.inputColNum"></app-graph> - <div id="layers-control"> +</div> +<div class="ns-row"> + + <div class ="ns-col" id="layers-control"> <div>Broj Skrivenih Slojeva</div> <button class="btn-clear btn-icon" (click)="addLayer()"> <mat-icon>add</mat-icon> @@ -102,18 +104,67 @@ <button class="btn-clear btn-icon" (click)="removeLayer()"> <mat-icon>remove</mat-icon> </button> + + </div> + <div class="break-1"></div> + <div class="ns-col"> + <mat-form-field appearance="fill"> + <mat-label>Aktivaciona funkcija svih slojeva</mat-label> + + <mat-select [(ngModel)]="selectedActivation" (selectionChange)="changeAllActivation()" > + <mat-option *ngFor="let option of Object.keys(ActivationFunction); let optionName of Object.values(ActivationFunction)" [value]="option"> + {{ optionName }} + </mat-option> + </mat-select> + </mat-form-field> + </div> + + <div class="ns-col"> + <mat-form-field appearance="fill"> + <mat-label>Broj Neurona svih slojeva</mat-label> + <input matInput type="number" [(ngModel)]="selectedNumberOfNeurons" (change)="changeAllNumberOfNeurons()"> + </mat-form-field> + </div> + <div class="break-2"></div> + <div class="ns-col"> + <mat-form-field appearance="fill"> + <mat-label>Regularizacija svih slojeva</mat-label> + <mat-select [(ngModel)]="selectedRegularisation" (selectionChange)="changeAllRegularisation()"> + <mat-option *ngFor="let option of Object.keys(Regularisation); let optionName of Object.values(Regularisation)" [value]="option"> + {{ optionName }} + </mat-option> + </mat-select> + </mat-form-field> </div> + + <div class="ns-col"> + <mat-form-field appearance="fill"> + <mat-label>Stopa regularizacije svih slojeva</mat-label> + <mat-select [(ngModel)]="selectedRegularisationRate" (selectionChange)="changeAllRegularisationRate()"> + <mat-option *ngFor="let option of Object.keys(RegularisationRate); let optionName of Object.values(RegularisationRate)" [value]="option"> + {{ optionName }} + </mat-option> + </mat-select> + </mat-form-field> + </div> + + </div> + +<!--kraj selectall**********************************************************************************--> <hr> <div id="layers"> <div class="layer" *ngFor="let item of newModel.layers; let i=index"> - <div class="text-center"> - #{{i+1}} - </div> + <mat-form-field appearance="fill"> - <mat-label>Aktivaciona funkcija</mat-label> + <mat-label>Aktivacija</mat-label> + <button matPrefix class="btn-clear center-center text-offwhite"> + <div> + #{{i+1}} + </div> + </button> <mat-select [(ngModel)]="newModel.layers[i].activationFunction"> <mat-option *ngFor="let option of Object.keys(ActivationFunction); let optionName of Object.values(ActivationFunction)" [value]="option"> {{ optionName }} @@ -126,7 +177,7 @@ <button class="btn-clear btn-icon" (click)="addNeuron(i)"> <mat-icon>add</mat-icon> </button> - <div class="col-1">{{newModel.layers[i].neurons}}</div> + <div class="col-2 text-center" >{{newModel.layers[i].neurons}}</div> <button class="btn-clear btn-icon" (click)="removeNeuron(i)"> <mat-icon>remove</mat-icon> </button> diff --git a/frontend/src/app/_elements/form-model/form-model.component.ts b/frontend/src/app/_elements/form-model/form-model.component.ts index c29fd0bb..062c380e 100644 --- a/frontend/src/app/_elements/form-model/form-model.component.ts +++ b/frontend/src/app/_elements/form-model/form-model.component.ts @@ -4,8 +4,7 @@ import Shared from 'src/app/Shared'; import Experiment from 'src/app/_data/Experiment'; import Model, { Layer, ActivationFunction, LossFunction, LearningRate, LossFunctionBinaryClassification, LossFunctionMultiClassification, LossFunctionRegression, Metrics, MetricsBinaryClassification, MetricsMultiClassification, MetricsRegression, NullValueOptions, Optimizer, ProblemType, Regularisation, RegularisationRate, BatchSize } from 'src/app/_data/Model'; import { GraphComponent } from '../graph/graph.component'; -import { FormGroupDirective, NgForm } from '@angular/forms'; -import { ErrorStateMatcher } from '@angular/material/core'; + @Component({ selector: 'app-form-model', @@ -104,4 +103,40 @@ export class FormModelComponent implements AfterViewInit { this.updateGraph(); } } + selectedActivation: ActivationFunction = ActivationFunction.Sigmoid; + selectedRegularisationRate: RegularisationRate = RegularisationRate.RR1; + selectedRegularisation: Regularisation = Regularisation.L1; + selectedNumberOfNeurons:number=1; + + changeAllActivation(){ + for(let i=0;i<this.newModel.layers.length;i++) + { + this.newModel.layers[i].activationFunction=this.selectedActivation; + + } + + } + changeAllRegularisation(){ + for(let i=0;i<this.newModel.layers.length;i++) + { + this.newModel.layers[i].regularisation=this.selectedRegularisation; + } + } + changeAllRegularisationRate(){ + + for(let i=0;i<this.newModel.layers.length;i++) + { + this.newModel.layers[i].regularisationRate=this.selectedRegularisationRate; + } + } + changeAllNumberOfNeurons(){ + for(let i=0;i<this.newModel.layers.length;i++) + { + this.newModel.layers[i].neurons=this.selectedNumberOfNeurons; + this.updateGraph(); + } + } + + + } diff --git a/frontend/src/app/_pages/experiment/experiment.component.html b/frontend/src/app/_pages/experiment/experiment.component.html index 1606adf5..5206c5f2 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.html +++ b/frontend/src/app/_pages/experiment/experiment.component.html @@ -28,7 +28,7 @@ </div> <div #steps id="step_2" class="step-content"> <div class="step-content-inside"> - <app-column-table></app-column-table> + <app-column-table (okPressed)="goToPage(2)"></app-column-table> </div> </div> <div #steps id="step_3" class="step-content"> diff --git a/frontend/src/custom-theme.scss b/frontend/src/custom-theme.scss index 8f716240..e8626080 100644 --- a/frontend/src/custom-theme.scss +++ b/frontend/src/custom-theme.scss @@ -1,7 +1,7 @@ /** * Generated theme by Material Theme Generator * https://materialtheme.arcsine.dev -* Fork at: https://materialtheme.arcsine.dev/?c=YHBhbGV0dGU$YHByaW1hcnk$YF48IzAwNjNhYiIsIj9lcjwjYjNkMGU2IiwiO2VyPCMwMDQ3OTF$LCIlPmBePCMwMGE4ZTgiLCI~ZXI8I2IzZTVmOCIsIjtlcjwjMDA4ZGRlfiwid2Fybj5gXjwjZjliN2I3IiwiP2VyPCNmZGU5ZTkiLCI7ZXI8I2Y2OWY5Zn4sIj9UZXh0PCMwMDQxNjUiLCI~PTwjZGZkN2Q3IiwiO1RleHQ8I2RmZDdkNyIsIjs9PCMwMDQxNjV$LCJmb250cz5bYEA8KC00fixgQDwoLTN$LGBAPCgtMn4sYEA8KC0xfixgQDxoZWFkbGluZX4sYEA8dGl0bGV$LGBAPHN1YiktMn4sYEA8c3ViKS0xfixgQDxib2R5LTJ$LGBAPGJvZHktMX4sYEA8YnV0dG9ufixgQDxjYXB0aW9ufixgQDxpbnB1dCIsInNpemU$bnVsbH1dLCJpY29uczxGaWxsZWQiLCI~bmVzcz5mYWxzZSwidmVyc2lvbj4xM30= +* Fork at: https://materialtheme.arcsine.dev/?c=YHBhbGV0dGU$YHByaW1hcnk$YF48IzAwYThlOCIsIj9lcjwjYjNlNWY4IiwiO2VyPCMwMDhkZGV$LCIlPmBePCMwMDYzYWIiLCI~ZXI8I2IzZDBlNiIsIjtlcjwjMDA0Nzkxfiwid2Fybj5gXjwjZjliN2I3IiwiP2VyPCNmZGU5ZTkiLCI7ZXI8I2Y2OWY5Zn4sIj9UZXh0PCNkZmQ3ZDciLCI~PTwjMDAzNDU5IiwiO1RleHQ8I2RmZDdkNyIsIjs9PCMwMDM0NTl$LCJmb250cz5bYEA8KC00fixgQDwoLTN$LGBAPCgtMn4sYEA8KC0xfixgQDxoZWFkbGluZX4sYEA8dGl0bGV$LGBAPHN1YiktMn4sYEA8c3ViKS0xfixgQDxib2R5LTJ$LGBAPGJvZHktMX4sYEA8YnV0dG9ufixgQDxjYXB0aW9ufixgQDxpbnB1dCIsInNpemU$bnVsbH1dLCJpY29uczxGaWxsZWQiLCI~bmVzcz5mYWxzZSwidmVyc2lvbj4xM30= */ @use '@angular/material' as mat; @@ -25,7 +25,7 @@ caption: mat.define-typography-level(12px, 20px, 400, 'Roboto', 0.0333em), input: mat.define-typography-level(inherit, 1.125, 400, 'Roboto', 1.5px)); // Foreground Elements // Light Theme Text -$dark-text: #004165; +$dark-text: #dfd7d7; $dark-primary-text: rgba($dark-text, 0.87); $dark-accent-text: rgba($dark-primary-text, @@ -83,7 +83,7 @@ slider-off-active: rgba($light-text, 0.3), ); // Background config // Light bg -$light-background : #dfd7d7; +$light-background : #003459; $light-bg-darker-5 : darken($light-background, 5%); $light-bg-darker-10 : darken($light-background, @@ -94,11 +94,11 @@ $light-bg-darker-30 : darken($light-background, 30%); $light-bg-lighter-5 : lighten($light-background, 5%); -$dark-bg-tooltip : lighten(#004165, +$dark-bg-tooltip : lighten(#003459, 20%); -$dark-bg-alpha-4 : rgba(#004165, +$dark-bg-alpha-4 : rgba(#003459, 0.04); -$dark-bg-alpha-12 : rgba(#004165, +$dark-bg-alpha-12 : rgba(#003459, 0.12); $mat-light-theme-background: ( background : $light-background, status-bar : $light-bg-darker-20, @@ -117,7 +117,7 @@ unselected-chip : $light-bg-darker-10, disabled-list-option : $light-bg-darker-10, ); // Dark bg -$dark-background : #004165; +$dark-background : #003459; $dark-bg-lighter-5 : lighten($dark-background, 5%); $dark-bg-lighter-10 : lighten($dark-background, @@ -126,9 +126,9 @@ $dark-bg-lighter-20 : lighten($dark-background, 20%); $dark-bg-lighter-30 : lighten($dark-background, 30%); -$light-bg-alpha-4 : rgba(#dfd7d7, +$light-bg-alpha-4 : rgba(#003459, 0.04); -$light-bg-alpha-12 : rgba(#dfd7d7, +$light-bg-alpha-12 : rgba(#003459, 0.12); // Background palette for dark themes. $mat-dark-theme-background: ( background : $dark-background, @@ -151,36 +151,36 @@ disabled-list-option : $dark-bg-lighter-10, @include mat.core($fontConfig); // Theme Config body { - --primary-color: #0063ab; - --primary-lighter-color: #b3d0e6; - --primary-darker-color: #004791; + --primary-color: #00a8e8; + --primary-lighter-color: #b3e5f8; + --primary-darker-color: #008dde; --text-primary-color: #{$light-primary-text}; --text-primary-lighter-color: #{$dark-primary-text}; --text-primary-darker-color: #{$light-primary-text}; } -$mat-primary: ( main: #0063ab, -lighter: #b3d0e6, -darker: #004791, -200: #0063ab, // For slide toggle, +$mat-primary: ( main: #00a8e8, +lighter: #b3e5f8, +darker: #008dde, +200: #00a8e8, // For slide toggle, contrast: ( main: $light-primary-text, lighter: $dark-primary-text, darker: $light-primary-text, )); $theme-primary: mat.define-palette($mat-primary, main, lighter, darker); body { - --accent-color: #00a8e8; - --accent-lighter-color: #b3e5f8; - --accent-darker-color: #008dde; + --accent-color: #0063ab; + --accent-lighter-color: #b3d0e6; + --accent-darker-color: #004791; --text-accent-color: #{$light-primary-text}; --text-accent-lighter-color: #{$dark-primary-text}; --text-accent-darker-color: #{$light-primary-text}; } -$mat-accent: ( main: #00a8e8, -lighter: #b3e5f8, -darker: #008dde, -200: #00a8e8, // For slide toggle, +$mat-accent: ( main: #0063ab, +lighter: #b3d0e6, +darker: #004791, +200: #0063ab, // For slide toggle, contrast: ( main: $light-primary-text, lighter: $dark-primary-text, darker: $light-primary-text, )); $theme-accent: mat.define-palette($mat-accent, main, diff --git a/frontend/src/styles/helper.css b/frontend/src/styles/helper.css index 55b0967e..c8d240f6 100644 --- a/frontend/src/styles/helper.css +++ b/frontend/src/styles/helper.css @@ -29,14 +29,9 @@ .footer-center { position: relative; height: 1rem; + text-align: center; } -.footer-center>* { - position: fixed; - bottom: 15px; - left: 50%; - transform: translateX(-50%); -} .row-height { white-space: nowrap; diff --git a/frontend/src/styles/layout.css b/frontend/src/styles/layout.css index 33f4cf2b..676bec32 100644 --- a/frontend/src/styles/layout.css +++ b/frontend/src/styles/layout.css @@ -15,4 +15,47 @@ body { .align-items-view>*:last-child { transform: perspective(100em) rotateY(-25deg) translateZ(1em); +} + +.ns-row { + width: 98%; + display: flex; + flex-direction: row; + flex-wrap: wrap; + margin: 0; + padding: 0; +} + +.ns-col { + flex-grow: 1; + padding: 2px; + margin-bottom: 0; + padding-bottom: 0; +} + +.break-1, +.break-2 { + height: 1px; + width: 100%; +} + +@media screen and (min-width: 1200px) { + .break-1 { + display: none; + } +} + +@media screen and (min-width: 2175px) { + .break-2 { + display: none; + } +} + +.center-center { + text-align: center; + margin-right: 10px; + padding-right: 10px; + padding-bottom: 15px; + font-size: 20px; + font-weight: 600; }
\ No newline at end of file |