aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/app/_elements
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/app/_elements')
-rw-r--r--frontend/src/app/_elements/dataset-load/dataset-load.component.ts100
-rw-r--r--frontend/src/app/_elements/model-load/model-load.component.html215
-rw-r--r--frontend/src/app/_elements/model-load/model-load.component.ts114
3 files changed, 429 insertions, 0 deletions
diff --git a/frontend/src/app/_elements/dataset-load/dataset-load.component.ts b/frontend/src/app/_elements/dataset-load/dataset-load.component.ts
new file mode 100644
index 00000000..73dbf2d2
--- /dev/null
+++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.ts
@@ -0,0 +1,100 @@
+import { Component, OnInit, ViewChild, ViewChildren } from '@angular/core';
+import { AddNewDatasetComponent } from '../add-new-dataset/add-new-dataset.component';
+import { ModelsService } from 'src/app/_services/models.service';
+import shared from 'src/app/Shared';
+import Dataset from 'src/app/_data/Dataset';
+import { DatatableComponent, TableData } from 'src/app/_elements/datatable/datatable.component';
+import { DatasetsService } from 'src/app/_services/datasets.service';
+import { CsvParseService } from 'src/app/_services/csv-parse.service';
+import { Output, EventEmitter } from '@angular/core';
+import { SignalRService } from 'src/app/_services/signal-r.service';
+
+@Component({
+ selector: 'app-dataset-load',
+ templateUrl: './dataset-load.component.html',
+ styleUrls: ['./dataset-load.component.css']
+})
+export class DatasetLoadComponent implements OnInit {
+
+ @Output() selectedDatasetChangeEvent = new EventEmitter<Dataset>();
+
+ @ViewChild(AddNewDatasetComponent) addNewDatasetComponent!: AddNewDatasetComponent;
+ @ViewChild(AddNewDatasetComponent) datatable!: DatatableComponent;
+
+ datasetLoaded: boolean = false;
+ selectedDatasetLoaded: boolean = false;
+
+ showMyDatasets: boolean = true;
+ myDatasets?: Dataset[];
+ existingDatasetSelected: boolean = false;
+ selectedDataset?: Dataset;
+
+ tableData: TableData = new TableData();
+
+ term: string = "";
+
+ constructor(private models: ModelsService, private datasets: DatasetsService, private csv: CsvParseService, private signalRService: SignalRService) {
+ this.datasets.getMyDatasets().subscribe((datasets) => {
+ this.myDatasets = datasets;
+ });
+ }
+
+ viewMyDatasetsForm() {
+ this.showMyDatasets = true;
+ if (this.selectedDataset != undefined)
+ this.resetSelectedDataset();
+ //this.resetCbsAndRbs(); //TREBA DA SE DESI
+ }
+ viewNewDatasetForm() {
+ this.showMyDatasets = false;
+ if (this.selectedDataset != undefined)
+ this.resetSelectedDataset();
+ //this.resetCbsAndRbs(); //TREBA DA SE DESI
+ }
+
+ refreshMyDatasets() {
+ this.datasets.getMyDatasets().subscribe((datasets) => {
+ this.myDatasets = datasets;
+ this.showMyDatasets = true;
+ });
+ }
+
+ selectThisDataset(dataset: Dataset) {
+ this.selectedDataset = dataset;
+ this.selectedDatasetLoaded = false;
+ this.existingDatasetSelected = true;
+ this.tableData.hasHeader = this.selectedDataset.hasHeader;
+
+ this.tableData.hasInput = true;
+ this.tableData.loaded = false;
+
+ this.datasets.getDatasetFile(dataset.fileId).subscribe((file: string | undefined) => {
+ if (file) {
+ this.tableData.loaded = true;
+ this.tableData.numRows = this.selectedDataset!.rowCount;
+ this.tableData.numCols = this.selectedDataset!.columnInfo.length;
+ this.tableData.data = this.csv.csvToArray(file, (dataset.delimiter == "razmak") ? " " : (dataset.delimiter == "") ? "," : dataset.delimiter);
+ //this.resetCbsAndRbs(); //TREBA DA SE DESI
+ //this.refreshThreeNullValueRadioOptions(); //TREBA DA SE DESI
+ this.selectedDatasetLoaded = true;
+
+ this.selectedDatasetChangeEvent.emit(this.selectedDataset);
+ }
+ });
+ }
+
+ resetSelectedDataset(): boolean {
+ this.selectedDatasetChangeEvent.emit(this.selectedDataset);
+ return true;
+ }
+
+ ngOnInit(): void {
+ if (this.signalRService.hubConnection) {
+ this.signalRService.hubConnection.on("NotifyDataset", _ => {
+ this.refreshMyDatasets();
+ });
+ } else {
+ console.warn("Dataset-Load: No connection!");
+ }
+ }
+}
diff --git a/frontend/src/app/_elements/model-load/model-load.component.html b/frontend/src/app/_elements/model-load/model-load.component.html
new file mode 100644
index 00000000..dcb35c21
--- /dev/null
+++ b/frontend/src/app/_elements/model-load/model-load.component.html
@@ -0,0 +1,215 @@
+<div>
+ <div class="d-flex flex-row justify-content-center align-items-center mt-3 mb-5">
+ <button type="button" id="btnMyModel" class="btn" (click)="viewMyModelsForm()"
+ [ngClass]="{'btnType1': showMyModels, 'btnType2': !showMyModels}">
+ Izaberite model iz kolekcije
+ </button>
+ <h3 class="mt-3 mx-3">ili</h3>
+ <button type="button" id="btnNewModel" class="btn" (click)="viewNewModelForm()"
+ [ngClass]="{'btnType1': !showMyModels, 'btnType2': showMyModels}">
+ Dodajte novi model
+ </button>
+ </div>
+
+ <div *ngIf="showMyModels" class="px-5 my-3">
+ <input *ngIf="showMyModels" type="text" class="form-control" placeholder="Pretraga" [(ngModel)]="term">
+ </div>
+ <div *ngIf="showMyModels" class="px-5">
+ <div class="overflow-auto" style="max-height: 500px;">
+ <ul class="list-group">
+ <li class="list-group-item p-3" *ngFor="let model of myModels|filter:term|filter:(forExperiment ? forExperiment.type : '')"
+ [ngClass]="{'selectedModelClass': this.selectedModel == model}">
+ <app-item-model name="usersModel" [model]="model" (click)="selectThisModel(model);">
+ </app-item-model>
+ </li>
+ </ul>
+ <div class="px-5 mt-5">
+ <!--prikaz izabranog modela-->
+ </div>
+ </div>
+ </div>
+
+
+ <div *ngIf="!showMyModels">
+ <div class="form-group row mt-3 mb-2 d-flex justify-content-center">
+
+ <div class="col-3">
+ <label for="name" class="col-form-label">Naziv modela:</label>
+ <input type="text" class="form-control" name="name" placeholder="Naziv..." [(ngModel)]="newModel.name">
+ </div>
+ <div class="col-5">
+ <label for="desc" class="col-sm-2 col-form-label">Opis:</label>
+ <div>
+ <textarea class="form-control" name="desc" rows="3" [(ngModel)]="newModel.description"></textarea>
+ </div>
+ </div>
+
+ </div>
+ <h2 class="mt-5 mb-4 mx-5">Parametri treniranja modela:</h2>
+ <div>
+
+ <div class="row p-2">
+ <div class="col-1"></div>
+ <div class="col-3">
+ <label for="type" class="col-form-label">Tip problema: </label>
+ </div>
+ <div class="col-2">
+ <select id=typeOptions class="form-select" name="type" [(ngModel)]="newModel.type"
+ (change)="filterOptions()">
+ <option
+ *ngFor="let option of Object.keys(ProblemType); let optionName of Object.values(ProblemType)"
+ [value]="option">
+ {{ optionName }}
+ </option>
+ </select>
+ </div>
+ <div class="col-1"></div>
+ <div class="col-3">
+ <label for="hiddenLayers" class="col-form-label">Broj skrivenih slojeva: </label>
+ </div>
+ <div class="col-1">
+ <input type="number" min="1" class="form-control" name="hiddenLayers"
+ [(ngModel)]="newModel.hiddenLayers"
+ (change)="newModel.hiddenLayerActivationFunctions = [].constructor(newModel.hiddenLayers).fill(newModel.hiddenLayerActivationFunctions[0])"
+ (ngModelChange)="updateGraph()">
+ </div>
+ </div>
+
+ <div class="row p-2">
+ <div class="col-1">
+ </div>
+ <div class="col-3">
+ <label for="optimizer" class="col-form-label">Optimizacija: </label>
+ </div>
+ <div class="col-2">
+ <select id=optimizerOptions class="form-select" name="optimizer" [(ngModel)]="newModel.optimizer">
+ <option
+ *ngFor="let option of Object.keys(Optimizer); let optionName of Object.values(Optimizer)"
+ [value]="option">
+ {{ optionName }}
+ </option>
+ </select>
+ </div>
+ <div class="col-1">
+ </div>
+ <div class="col-3">
+ <label for="hiddenLayerNeurons" class="col-form-label">Broj neurona skrivenih slojeva: </label>
+ </div>
+ <div class="col-1">
+ <input type="number" min="1" class="form-control" name="hiddenLayerNeurons"
+ [(ngModel)]="newModel.hiddenLayerNeurons" (ngModelChange)="updateGraph()">
+ </div>
+ </div>
+
+ <div class="row p-2">
+ <div class="col-1"></div>
+ <div class="col-3">
+ <label for="lossFunction" class="col-form-label">Funkcija troška: </label>
+ </div>
+ <div class="col-2">
+ <select id=lossFunctionOptions class="form-select" name="lossFunction"
+ [(ngModel)]="newModel.lossFunction" aria-checked="true">
+ <option
+ *ngFor="let option of Object.keys(lossFunction); let optionName of Object.values(lossFunction)"
+ [value]="option">
+ {{ optionName }}
+ </option>
+ </select>
+ </div>
+ <div class="col-1"></div>
+ <div class="col-3">
+ <label for="batchSize" class="col-form-label">Broj uzorka po iteraciji: </label>
+ </div>
+ <div class="col-1">
+
+ <input type="number" min="0" step="1" max="7" class="form-control" name="batchSizePower" [(ngModel)]="batchSizePower" (click)="updateBatchSize()" >
+ {{newModel.batchSize}}
+
+ </div>
+
+ <div class="row p-2">
+ <div class="col-1"></div>
+ <div class="col-3 m-1">
+ <label for="epochs" class="col-form-label">Broj epoha: </label>
+ </div>
+ <div class="col-1">
+ <input type="number" min="1" max="1000" class="form-control" name="epochs"
+ [(ngModel)]="newModel.epochs">
+ </div>
+ </div>
+ </div>
+
+ <div class="m-5">
+ <app-graph [model]="newModel" [inputCols]="1"></app-graph>
+ </div>
+
+ <h3 class="mx-5 mt-4">Aktivacione funkcije:</h3>
+
+ <div class="row p-2" style="align-self: center;">
+ <div class="col-1"></div>
+ <div class="col-3">
+ <label for="hiddenLayerActivationFunction" class="col-form-label"
+ style="text-align: center;">Funkcija aktivacije<br>skrivenih slojeva:</label>
+ </div>
+ <div class="col-2 mt-2">
+ <div *ngFor="let item of [].constructor(newModel.hiddenLayers); let i = index">
+ <div class="input-group mb-2">
+ <div class="input-group-prepend">
+ <span class="input-group-text">#{{i+1}}</span>
+ </div>
+ <select [id]="'hiddenLayerActivationFunctionOption_'+i" class="form-select"
+ [(ngModel)]="newModel.hiddenLayerActivationFunctions[i]" >
+ <option
+ *ngFor="let option of Object.keys(ActivationFunction); let optionName of Object.values(ActivationFunction)"
+ [value]="option">
+ {{ optionName }}
+ </option>
+ </select>
+ </div>
+ </div>
+ </div>
+ <div class="col-1"></div>
+ <div class="col-2">
+ <label for="outputLayerActivationFunction" class="col-form-label"
+ style="text-align: center;">Funkcija aktivacije<br>izlaznog sloja:</label>
+ </div>
+ <div class="col-2 mt-2">
+ <select id=outputLayerActivationFunctionOptions class="form-select"
+ name="outputLayerActivationFunction" [(ngModel)]="newModel.outputLayerActivationFunction">
+ <option
+ *ngFor="let option of Object.keys(ActivationFunction); let optionName of Object.values(ActivationFunction)"
+ [value]="option">
+ {{ optionName }}
+ </option>
+ </select>
+ </div>
+ <div class="col">
+ </div>
+ </div>
+ </div>
+
+ <div class="form-check form-check-inline overflow-auto m-4" style="width: max-content;">
+ <h3>Izaberite metrike:</h3>
+ <div id="divMetricsinput" class="mt-2 mx-5">
+
+ <div *ngFor="let option of Object.keys(metrics); let optionName of Object.values(metrics) "
+ class="form-check form-check-inline">
+
+ <input name="cbmetrics" class="form-check-input" type="checkbox" value="{{option}}"
+ id="metrics_{{option}}" style="float: left;" checked>
+ <label class="form-check-label" for="metrics_{{option}}" for="inlineCheckbox2">
+ {{optionName}}
+ </label>
+ </div>
+ </div>
+ </div>
+
+ <div class="form-group row mt-3 mb-3">
+ <div class="col"></div>
+ <button class="btn btn-lg col-4" style="background-color:#003459; color:white;"
+ (click)="uploadModel();">Sačuvaj
+ model</button>
+ <div class="col"></div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_elements/model-load/model-load.component.ts b/frontend/src/app/_elements/model-load/model-load.component.ts
new file mode 100644
index 00000000..dbca3d17
--- /dev/null
+++ b/frontend/src/app/_elements/model-load/model-load.component.ts
@@ -0,0 +1,114 @@
+import { Component, OnInit, ViewChild, Output, EventEmitter, Input } from '@angular/core';
+import Shared from 'src/app/Shared';
+import Experiment from 'src/app/_data/Experiment';
+import Model, { ActivationFunction, LossFunction, LossFunctionBinaryClassification, LossFunctionMultiClassification, LossFunctionRegression, Metrics, MetricsBinaryClassification, MetricsMultiClassification, MetricsRegression, NullValueOptions, Optimizer, ProblemType } from 'src/app/_data/Model';
+import { ModelsService } from 'src/app/_services/models.service';
+import { GraphComponent } from '../graph/graph.component';
+
+
+@Component({
+ selector: 'app-model-load',
+ templateUrl: './model-load.component.html',
+ styleUrls: ['./model-load.component.css']
+})
+export class ModelLoadComponent implements OnInit {
+
+ @ViewChild(GraphComponent) graph!: GraphComponent;
+ @Input() forExperiment?:Experiment;
+ @Output() selectedModelChangeEvent = new EventEmitter<Model>();
+
+ newModel: Model = new Model();
+ myModels?: Model[];
+ selectedModel?: Model;
+
+ ProblemType = ProblemType;
+ ActivationFunction = ActivationFunction;
+ metrics: any = Metrics;
+ LossFunction = LossFunction;
+ Optimizer = Optimizer;
+ Object = Object;
+ document = document;
+ shared = Shared;
+
+ term: string = "";
+ selectedProblemType: string = '';
+ selectedMetrics = [];
+ lossFunction: any = LossFunction;
+
+ showMyModels: boolean = true;
+
+ constructor(private modelsService: ModelsService) {
+ this.modelsService.getMyModels().subscribe((models) => {
+ this.myModels = models;
+ });
+ }
+
+ ngOnInit(): void {
+ }
+ batchSizePower:number=1;
+ updateBatchSize()
+ {
+ this.newModel.batchSize=2**this.batchSizePower;
+ }
+
+ updateGraph() {
+ this.graph.update();
+ }
+
+ getMetrics() {
+ this.newModel.metrics = [];
+ let cb = document.getElementsByName("cbmetrics");
+
+ for (let i = 0; i < cb.length; i++) {
+ let chb = <HTMLInputElement>cb[i];
+ if (chb.checked == true)
+ this.newModel.metrics.push(chb.value);
+ }
+ }
+
+ uploadModel() {
+ this.getMetrics();
+
+ this.newModel.uploaderId = Shared.userId;
+
+ this.modelsService.addModel(this.newModel).subscribe((response) => {
+ Shared.openDialog('Model dodat', 'Model je uspešno dodat u bazu.');
+ // treba da se selektuje nov model u listi modela
+ //this.selectedModel =
+ }, (error) => {
+ Shared.openDialog('Greška', 'Model sa unetim nazivom već postoji u Vašoj kolekciji. Promenite naziv modela i nastavite sa kreiranim datasetom.');
+ });
+ }
+
+ filterOptions() {
+ switch (this.newModel.type) {
+ case 'regresioni':
+ this.lossFunction = LossFunctionRegression;
+ this.metrics = MetricsRegression;
+ break;
+ case 'binarni-klasifikacioni':
+ this.lossFunction = LossFunctionBinaryClassification;
+ this.metrics = MetricsBinaryClassification;
+ break;
+ case 'multi-klasifikacioni':
+ this.lossFunction = LossFunctionMultiClassification;
+ this.metrics = MetricsMultiClassification;
+ break;
+ default:
+ break;
+ }
+ }
+
+ viewMyModelsForm() {
+ this.showMyModels = true;
+ }
+ viewNewModelForm() {
+ this.showMyModels = false;
+ }
+
+ selectThisModel(model: Model) {
+ this.selectedModel = model;
+ this.selectedModelChangeEvent.emit(this.selectedModel);
+ }
+
+}