aboutsummaryrefslogtreecommitdiff
path: root/frontend
diff options
context:
space:
mode:
Diffstat (limited to 'frontend')
-rw-r--r--frontend/src/app/_elements/_charts/box-plot/box-plot.component.html4
-rw-r--r--frontend/src/app/_elements/_charts/box-plot/box-plot.component.ts25
-rw-r--r--frontend/src/app/_elements/_charts/pie-chart/pie-chart.component.html4
-rw-r--r--frontend/src/app/_elements/_charts/pie-chart/pie-chart.component.ts10
-rw-r--r--frontend/src/app/_elements/column-table/column-table.component.css60
-rw-r--r--frontend/src/app/_elements/column-table/column-table.component.html57
-rw-r--r--frontend/src/app/_elements/column-table/column-table.component.ts38
-rw-r--r--frontend/src/styles/helper.css6
-rw-r--r--frontend/src/styles/theme.css3
9 files changed, 143 insertions, 64 deletions
diff --git a/frontend/src/app/_elements/_charts/box-plot/box-plot.component.html b/frontend/src/app/_elements/_charts/box-plot/box-plot.component.html
index 34c283c7..688eafae 100644
--- a/frontend/src/app/_elements/_charts/box-plot/box-plot.component.html
+++ b/frontend/src/app/_elements/_charts/box-plot/box-plot.component.html
@@ -1 +1,3 @@
-<canvas #boxplot [width]="width" [height]="height"></canvas> \ No newline at end of file
+<div class="chart-wrapper">
+ <canvas #boxplot [width]="width" [height]="height"></canvas>
+</div> \ No newline at end of file
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 45e83e83..3faa4794 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,8 +16,8 @@ Chart.register(BoxPlotController, BoxAndWiskers, LinearScale, CategoryScale);
})
export class BoxPlotComponent implements AfterViewInit {
- @Input()width: number = 600;
- @Input()height: number = 800;
+ @Input()width?: number;
+ @Input()height?: number;
@ViewChild('boxplot') chartRef!: ElementRef;
constructor() { }
@@ -27,10 +27,11 @@ export class BoxPlotComponent implements AfterViewInit {
labels: ['January'/*, 'February', 'March', 'April', 'May', 'June', 'July'*/],
datasets: [{
label: 'Dataset 1',
- backgroundColor: 'rgba(255,0,0,0.5)',
- borderColor: 'red',
+ backgroundColor: 'rgba(0, 65, 101, 1.0)',
+ borderColor: '#0063AB',
borderWidth: 1,
outlierColor: '#999999',
+ scaleFontColor: '#0063AB',
padding: 10,
itemRadius: 0,
data: [
@@ -75,9 +76,23 @@ export class BoxPlotComponent implements AfterViewInit {
},
},
scales : {
+ x: {
+ ticks: {
+ color: 'rgba(0, 65, 101, 1.0)'
+ },
+ grid: {
+ color: "rgba(0, 99, 171, 0.5)"
+ }
+ },
y : {
min: -50,
- max: 200
+ max: 200,
+ ticks: {
+ color: 'rgba(0, 65, 101, 1.0)'
+ },
+ grid: {
+ color: "rgba(0, 99, 171, 0.5)"
+ }
}
}
}
diff --git a/frontend/src/app/_elements/_charts/pie-chart/pie-chart.component.html b/frontend/src/app/_elements/_charts/pie-chart/pie-chart.component.html
index aa3f26ab..7faf3af0 100644
--- a/frontend/src/app/_elements/_charts/pie-chart/pie-chart.component.html
+++ b/frontend/src/app/_elements/_charts/pie-chart/pie-chart.component.html
@@ -1 +1,3 @@
-<canvas #piechart [width]="width" [height]="height"></canvas>
+<div class="chart-wrapper">
+ <canvas #piechart [width]="width" [height]="height"></canvas>
+</div> \ No newline at end of file
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 248c9aa8..f141f522 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
@@ -8,8 +8,8 @@ import {Chart} from 'chart.js';
})
export class PieChartComponent implements AfterViewInit {
- @Input()width: number = 600;
- @Input()height: number = 450;
+ @Input()width?: number;
+ @Input()height?: number;
@ViewChild('piechart') chartRef!: ElementRef;
constructor() { }
@@ -22,7 +22,7 @@ export class PieChartComponent implements AfterViewInit {
datasets: [{
label: "Population (millions)",
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
- data: [2478,5267,734,784,433]
+ data: [2478,5267,734,784,433],
}]
},
options: {
@@ -34,7 +34,9 @@ export class PieChartComponent implements AfterViewInit {
legend: {
display: false
},
- }
+ },
+ layout: {
+ padding: 15}
}
});
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 0db50cdb..1e7d4745 100644
--- a/frontend/src/app/_elements/column-table/column-table.component.css
+++ b/frontend/src/app/_elements/column-table/column-table.component.css
@@ -3,18 +3,25 @@ table.fixed {
display: block;
overflow-x: auto;
white-space: nowrap;
+ border: 1px solid var(--ns-primary-50);
+ font-size: 12px;
+ border-radius: 4px;
}
table.fixed td {
overflow: hidden;
max-width: 200px;
vertical-align: middle;
+ background-color: var(--ns-bg-dark-100);
+ margin: 4px;
}
table.fixed th {
overflow: hidden;
max-width: 350px;
vertical-align: middle;
+ background-color: var(--ns-bg-dark-100);
+ font-size: 14px;
}
table.fixed th:first-child {
@@ -28,6 +35,11 @@ table.fixed th:first-child {
.brighter {
background-color: var(--ns-primary) !important;
+ border-color: var(--offwhite);
+}
+
+.border-bottom {
+ border-bottom-color: var(--offwhite) !important;
}
mat-slider {
@@ -40,4 +52,52 @@ mat-slider {
.slider {
background-color: var(--ns-bg-dark-100);
+}
+
+#missingValuesHeader {
+ font-size: 12px;
+ line-height: 110% !important;
+}
+
+.verticalAlign {
+ vertical-align: center;
+}
+
+.cell-align {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ height: 100%;
+}
+
+table ::ng-deep .mat-form-field-wrapper {
+ margin-top: -2rem;
+}
+
+.graphics-row {
+ height: 100px;
+ padding: 1px;
+ margin: 0;
+}
+
+.no-pad {
+ padding: 1px;
+ margin: 0;
+}
+
+.text-overflow {
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+.row-height {
+ height: 30px;
+ border: none;
+ outline: none;
+}
+
+.graphic-class {
+ background-color: white !important;
} \ 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 55c07b87..92a4699a 100644
--- a/frontend/src/app/_elements/column-table/column-table.component.html
+++ b/frontend/src/app/_elements/column-table/column-table.component.html
@@ -3,8 +3,10 @@
<tr>
<th>Naziv</th>
<th class="columnNames" *ngFor="let colInfo of dataset.columnInfo; let i = index">
- #{{i + 1}}&nbsp;&nbsp;{{colInfo.columnName}}
- <mat-checkbox checked (change)="changeInputColumns($event, colInfo.columnName)"></mat-checkbox>
+ <div class="cell-align">
+ #{{i + 1}}&nbsp;&nbsp;{{colInfo.columnName}}
+ <mat-checkbox checked (change)="changeInputColumns($event, colInfo.columnName)"></mat-checkbox>
+ </div>
</th>
</tr>
</thead>
@@ -20,11 +22,11 @@
</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>
- <app-pie-chart *ngIf="!colInfo.isNumber"></app-pie-chart>
+ <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>
@@ -40,16 +42,17 @@
Q3: {{colInfo.q3}}<br>
-->
</span>
- <span *ngIf="!colInfo.isNumber">
+ <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>
- </span>
+ </div>
</td>
</tr>
<tr style="padding: 0">
- <th class="brighter" (click)="openEncodingDialog()">Enkoding
- <span class="material-icons-round">settings</span>
+ <th class="brighter cell-align" (click)="openEncodingDialog()">
+ <span class="verticalAlign">Enkodiranje</span>&nbsp;
+ <span class="material-icons-round verticalAlign">settings</span>
</th>
<td *ngFor="let colInfo of dataset.columnInfo; let i = index">
<mat-form-field>
@@ -62,25 +65,29 @@
</td>
</tr>
<tr>
- <th class="brighter" (click)="openMissingValuesDialog()">Regulisanje<br>nedostajućih<br>vrednosti<br>
+ <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 mat-button [matMenuTriggerFor]="menu" id="main_{{colInfo.columnName}}" #nullValMenu>
- Prikaži opcije<span class="material-icons">arrow_drop_down</span>
+ <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)" value={{colInfo.columnName}}>Obriši kolonu</button>
- <button mat-menu-item (click)="MissValsDeleteClicked($event, NullValueOptions.DeleteRows)" value={{colInfo.columnName}}>Obriši redove</button>
+ <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)" value={{colInfo.mean}}>Mean ({{colInfo.mean}})</button>
- <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName)" value={{colInfo.median}}>Median ({{colInfo.median}})</button>
- <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName)" value={{colInfo.max}}>Max ({{colInfo.max}})</button>
- <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName)" value={{colInfo.min}}>Min ({{colInfo.min}})</button>
+ <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>
@@ -88,22 +95,22 @@
</mat-menu>
<mat-menu #uniques="matMenu">
- <button mat-menu-item *ngFor="let uniqueValue of colInfo.uniqueValues" (click)="MissValsReplaceClicked($event, colInfo.columnName)" value={{uniqueValue}}>{{uniqueValue}}</button>
+ <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)">Potvrdi unos</button>
+ <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 *ngFor="let row of tableData; let i = index">
+ <tr class="row-height" *ngFor="let row of tableData; let i = index">
<th *ngIf="i == 0" [attr.rowspan]="tableData!.length">Vrednosti</th>
- <td *ngFor="let col of row; let j = index">
- <div style="overflow: auto">
+ <td class="text-center" *ngFor="let col of row; let j = index">
+ <div class="text-overflow">
{{col}}
</div>
</td>
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 9cb038bc..85046b8c 100644
--- a/frontend/src/app/_elements/column-table/column-table.component.ts
+++ b/frontend/src/app/_elements/column-table/column-table.component.ts
@@ -7,7 +7,6 @@ import { MatDialog } from '@angular/material/dialog';
import { MissingvaluesDialogComponent } from 'src/app/_modals/missingvalues-dialog/missingvalues-dialog.component';
import { MatSliderChange } from '@angular/material/slider';
import { MatCheckboxChange } from '@angular/material/checkbox';
-import { MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
import { CsvParseService } from 'src/app/_services/csv-parse.service';
@Component({
@@ -25,7 +24,7 @@ export class ColumnTableComponent implements AfterViewInit {
Encoding = Encoding;
NullValueOptions = NullValueOptions;
tableData?: any[][];
- nesto = 10;
+ nullValOption: string[] = [];
testSetDistribution:number=70;
constructor(private datasetService: DatasetsService, public csvParseService: CsvParseService, public dialog: MatDialog) {
@@ -35,7 +34,6 @@ export class ColumnTableComponent implements AfterViewInit {
ngAfterViewInit(): void {
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);
@@ -43,39 +41,27 @@ export class ColumnTableComponent implements AfterViewInit {
this.resetColumnEncodings(Encoding.Label);
this.setDeleteColumnsForMissingValTreatment();
- /*this.datasetService.getDatasetFile(this.dataset._id).subscribe((file: string | undefined) => {
- if (file) {
- //this.tableData = this.csv.csvToArray(file, (dataset.delimiter == "razmak") ? " " : (dataset.delimiter == "") ? "," : dataset.delimiter);
- }
- });*/
+ this.nullValOption = [].constructor(this.dataset.columnInfo.length).fill('Obriši redove');
+
this.datasetService.getDatasetFilePartial(this.dataset.fileId, 0, 10).subscribe((response: string | undefined) => {
if (response && this.dataset != undefined) {
this.tableData = this.csvParseService.csvToArray(response, (this.dataset.delimiter == "razmak") ? " " : (this.dataset.delimiter == "") ? "," : this.dataset.delimiter);
- console.log(this.tableData);
}
});
});
}
setDeleteColumnsForMissingValTreatment() {
- console.log("USAOOOO");
if (this.experiment != undefined) {
- this.experiment.nullValues = NullValueOptions.DeleteColumns;
+ this.experiment.nullValues = NullValueOptions.DeleteRows;
this.experiment.nullValuesReplacers = [];
- console.log("duzina",this.experiment.inputColumns.length);
for (let i = 0; i < this.experiment.inputColumns.length; i++) {
this.experiment.nullValuesReplacers.push({
column: this.experiment.inputColumns[i],
- option: NullValueOptions.DeleteColumns,
+ option: NullValueOptions.DeleteRows,
value: ""
});
- console.log(i);
}
- //console.log("len",this.nullValMenus.length);
- this.nullValMenus.forEach((menu) => {
- //console.log(menu.nativeElement);
- menu.nativeElement.textContent = "Obriši kolonu";
- });
}
}
@@ -127,7 +113,7 @@ export class ColumnTableComponent implements AfterViewInit {
option: NullValueOptions.DeleteColumns,
value: ""
});
- (<HTMLInputElement>document.getElementById("main_" + this.experiment.inputColumns[i])).textContent = "Obriši kolonu";
+ this.nullValOption[i] = "Obriši kolonu";
}
}
else if (selectedMissingValuesOption == NullValueOptions.DeleteRows) {
@@ -139,7 +125,7 @@ export class ColumnTableComponent implements AfterViewInit {
option: NullValueOptions.DeleteRows,
value: ""
});
- (<HTMLInputElement>document.getElementById("main_" + this.experiment.inputColumns[i])).textContent = "Obriši redove";
+ this.nullValOption[i] = "Obriši redove";
}
}
}
@@ -158,7 +144,7 @@ export class ColumnTableComponent implements AfterViewInit {
}
- MissValsDeleteClicked(event: Event, replacementType: NullValueOptions) {
+ MissValsDeleteClicked(event: Event, replacementType: NullValueOptions, index: number) {
if (this.experiment != undefined) {
let columnName = (<HTMLInputElement>event.currentTarget).value;
let arrayElement = this.experiment.nullValuesReplacers.filter(x => x.column == columnName)[0];
@@ -174,12 +160,12 @@ export class ColumnTableComponent implements AfterViewInit {
arrayElement.option = (replacementType == NullValueOptions.DeleteColumns) ? NullValueOptions.DeleteColumns : NullValueOptions.DeleteRows;
arrayElement.value = "";
}
-
- (<HTMLInputElement>document.getElementById("main_" + columnName)).textContent = (replacementType == NullValueOptions.DeleteColumns) ? "Obriši kolonu" : "Obriši redove";
+
+ this.nullValOption[index] = (replacementType == NullValueOptions.DeleteColumns) ? "Obriši kolonu" : "Obriši redove";
}
}
- MissValsReplaceClicked(event: Event, columnName: string) {
+ MissValsReplaceClicked(event: Event, columnName: string, index: number) {
if (this.experiment != undefined) {
let fillValue = (<HTMLInputElement>event.currentTarget).value;
let arrayElement = this.experiment.nullValuesReplacers.filter(x => x.column == columnName)[0];
@@ -196,7 +182,7 @@ export class ColumnTableComponent implements AfterViewInit {
arrayElement.value = fillValue;
}
- (<HTMLInputElement>document.getElementById("main_" + columnName)).textContent = "Popuni sa: " + fillValue;
+ this.nullValOption[index] = "Popuni sa: " + fillValue;
}
}
getValue(columnName: string): string {
diff --git a/frontend/src/styles/helper.css b/frontend/src/styles/helper.css
index fa362803..ef875069 100644
--- a/frontend/src/styles/helper.css
+++ b/frontend/src/styles/helper.css
@@ -122,4 +122,10 @@
.bg-blur {
backdrop-filter: blur(2px);
+}
+
+.chart-wrapper {
+ width: 150px;
+ height: 150px;
+ margin: auto;
} \ No newline at end of file
diff --git a/frontend/src/styles/theme.css b/frontend/src/styles/theme.css
index f9ea219f..17a433c6 100644
--- a/frontend/src/styles/theme.css
+++ b/frontend/src/styles/theme.css
@@ -8,8 +8,7 @@
--ns-bg-dark-100: rgba(0, 65, 101, 1.0);
--ns-bg-dark-50: rgba(0, 65, 101, 0.5);
--offwhite: #dfd7d7;
- --ns-warn:#f9b7b7;
-
+ --ns-warn: #f9b7b7;
}
body {