diff options
Diffstat (limited to 'frontend')
23 files changed, 352 insertions, 107 deletions
diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 488653db..d44f86d1 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -25,14 +25,16 @@ "@ng-bootstrap/ng-bootstrap": "^12.0.0", "@popperjs/core": "^2.10.2", "bootstrap": "^5.1.3", + "canvasjs": "^1.8.3", "chart.js": "^3.7.1", + "chartjs-plugin-datalabels": "^0.7.0", "csv-parser": "^3.0.0", "d3-graphviz": "^2.6.1", "jquery": "^3.6.0", "mdb-angular-ui-kit": "^2.0.0", "ng-multiselect-dropdown": "^0.3.8", "ng-uikit-pro-standard": "^1.0.0", - "ng2-charts": "^3.0.8", + "ng2-charts": "^3.0.9", "ng2-search-filter": "^0.5.1", "ngx-cookie-service": "^13.1.2", "popper.js": "^1.16.1", @@ -45,6 +47,7 @@ "@angular-devkit/build-angular": "~13.2.5", "@angular/cli": "~13.2.5", "@angular/compiler-cli": "~13.2.0", + "@types/canvasjs": "^1.9.7", "@types/crypto-js": "^4.1.1", "@types/d3-graphviz": "^2.6.7", "@types/jasmine": "~3.10.0", @@ -2737,6 +2740,12 @@ "@types/node": "*" } }, + "node_modules/@types/canvasjs": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@types/canvasjs/-/canvasjs-1.9.7.tgz", + "integrity": "sha512-/CfA3VtyTYVXDHvMy8F5hsvRUTiBX7TGe+nAHNONoJlNHbqakeIzxxt1MSNH619s8Oiu4CcFBMmJVg50El/0lw==", + "dev": true + }, "node_modules/@types/component-emitter": { "version": "1.2.11", "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", @@ -3420,9 +3429,9 @@ } }, "node_modules/async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dev": true, "dependencies": { "lodash": "^4.17.14" @@ -3883,6 +3892,11 @@ "url": "https://opencollective.com/browserslist" } }, + "node_modules/canvasjs": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/canvasjs/-/canvasjs-1.8.3.tgz", + "integrity": "sha512-60eUT0VjqRgYqdIQcOkXg0Zptfbl4HefA/O51YEf1m/P0uXvE3icI/1KPrXpY9aVxn8gG/BB8DzVoTGCcyBnYg==" + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -3907,6 +3921,14 @@ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.7.1.tgz", "integrity": "sha512-8knRegQLFnPQAheZV8MjxIXc5gQEfDFD897BJgv/klO/vtIyFFmgMXrNfgrXpbTr/XbTturxRgxIXx/Y+ASJBA==" }, + "node_modules/chartjs-plugin-datalabels": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-0.7.0.tgz", + "integrity": "sha512-PKVUX14nYhH0wcdCpgOoC39Gbzvn6cZ7O9n+bwc02yKD9FTnJ7/TSrBcfebmolFZp1Rcicr9xbT0a5HUbigS7g==", + "peerDependencies": { + "chart.js": ">= 2.7.0 < 3" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -8213,9 +8235,9 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/ng2-charts": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-3.0.8.tgz", - "integrity": "sha512-ELlpN0b/IJO4ka/P2sFBKeng3bV7XOQuh40f0J5hx9UveWPaSxOYQAOiGxV7BN2VSnKq6GRkjRvqTrcQPyJYww==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-3.0.9.tgz", + "integrity": "sha512-VKUd0lMhDb/IC4WGYH/CW29HlMibXGMK+Ik/T+M0uR98Ox+YEQUPsrqbroF/cWMxVf2XuTkFGaUn2fbqlDBSOQ==", "dependencies": { "lodash-es": "^4.17.15", "tslib": "^2.3.0" @@ -13747,6 +13769,12 @@ "@types/node": "*" } }, + "@types/canvasjs": { + "version": "1.9.7", + "resolved": "https://registry.npmjs.org/@types/canvasjs/-/canvasjs-1.9.7.tgz", + "integrity": "sha512-/CfA3VtyTYVXDHvMy8F5hsvRUTiBX7TGe+nAHNONoJlNHbqakeIzxxt1MSNH619s8Oiu4CcFBMmJVg50El/0lw==", + "dev": true + }, "@types/component-emitter": { "version": "1.2.11", "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", @@ -14355,9 +14383,9 @@ "dev": true }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dev": true, "requires": { "lodash": "^4.17.14" @@ -14699,6 +14727,11 @@ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==" }, + "canvasjs": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/canvasjs/-/canvasjs-1.8.3.tgz", + "integrity": "sha512-60eUT0VjqRgYqdIQcOkXg0Zptfbl4HefA/O51YEf1m/P0uXvE3icI/1KPrXpY9aVxn8gG/BB8DzVoTGCcyBnYg==" + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -14720,6 +14753,12 @@ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.7.1.tgz", "integrity": "sha512-8knRegQLFnPQAheZV8MjxIXc5gQEfDFD897BJgv/klO/vtIyFFmgMXrNfgrXpbTr/XbTturxRgxIXx/Y+ASJBA==" }, + "chartjs-plugin-datalabels": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-0.7.0.tgz", + "integrity": "sha512-PKVUX14nYhH0wcdCpgOoC39Gbzvn6cZ7O9n+bwc02yKD9FTnJ7/TSrBcfebmolFZp1Rcicr9xbT0a5HUbigS7g==", + "requires": {} + }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -17885,9 +17924,9 @@ } }, "ng2-charts": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-3.0.8.tgz", - "integrity": "sha512-ELlpN0b/IJO4ka/P2sFBKeng3bV7XOQuh40f0J5hx9UveWPaSxOYQAOiGxV7BN2VSnKq6GRkjRvqTrcQPyJYww==", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-3.0.9.tgz", + "integrity": "sha512-VKUd0lMhDb/IC4WGYH/CW29HlMibXGMK+Ik/T+M0uR98Ox+YEQUPsrqbroF/cWMxVf2XuTkFGaUn2fbqlDBSOQ==", "requires": { "lodash-es": "^4.17.15", "tslib": "^2.3.0" diff --git a/frontend/package.json b/frontend/package.json index 7df35a97..87b21e05 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -28,6 +28,7 @@ "@ng-bootstrap/ng-bootstrap": "^12.0.0", "@popperjs/core": "^2.10.2", "bootstrap": "^5.1.3", + "canvasjs": "^1.8.3", "chart.js": "^3.7.1", "chartjs-plugin-datalabels": "^0.7.0", "csv-parser": "^3.0.0", @@ -49,6 +50,7 @@ "@angular-devkit/build-angular": "~13.2.5", "@angular/cli": "~13.2.5", "@angular/compiler-cli": "~13.2.0", + "@types/canvasjs": "^1.9.7", "@types/crypto-js": "^4.1.1", "@types/d3-graphviz": "^2.6.7", "@types/jasmine": "~3.10.0", diff --git a/frontend/src/app/_elements/dataset-load/dataset-load.component.ts b/frontend/src/app/_elements/dataset-load/dataset-load.component.ts index b2f8857d..be1dc097 100644 --- a/frontend/src/app/_elements/dataset-load/dataset-load.component.ts +++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.ts @@ -8,6 +8,7 @@ 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'; +import { AuthService } from 'src/app/_services/auth.service'; @Component({ selector: 'app-dataset-load', @@ -33,7 +34,15 @@ export class DatasetLoadComponent implements OnInit { term: string = ""; - constructor(private models: ModelsService, private datasets: DatasetsService, private csv: CsvParseService, private signalRService: SignalRService) { + constructor(private models: ModelsService, private datasets: DatasetsService, private csv: CsvParseService, private signalRService: SignalRService, private authService: AuthService) { + this.fetchDatasets(); + + authService.loggedInEvent.subscribe(_ => { + this.fetchDatasets(); + }) + } + + fetchDatasets() { this.datasets.getMyDatasets().subscribe((datasets) => { this.myDatasets = datasets; }); diff --git a/frontend/src/app/_elements/line-chart/line-chart.component.html b/frontend/src/app/_elements/line-chart/line-chart.component.html index 8607aac5..c8f406f4 100644 --- a/frontend/src/app/_elements/line-chart/line-chart.component.html +++ b/frontend/src/app/_elements/line-chart/line-chart.component.html @@ -1,9 +1,5 @@ <div class="chart-wrapper"> - <canvas baseChart - [datasets]="lineChartData" - [labels]="lineChartLabels" - [options]="lineChartOptions" - [legend]="lineChartLegend" - [plugins]="lineChartPlugins"> + <canvas id="myChart"> + </canvas> </div>
\ No newline at end of file diff --git a/frontend/src/app/_elements/line-chart/line-chart.component.ts b/frontend/src/app/_elements/line-chart/line-chart.component.ts index 7a06ecf5..68663861 100644 --- a/frontend/src/app/_elements/line-chart/line-chart.component.ts +++ b/frontend/src/app/_elements/line-chart/line-chart.component.ts @@ -1,57 +1,39 @@ -import { Component, OnInit } from '@angular/core'; -import { ChartOptions } from 'chart.js'; +import { Component, OnInit,Input } from '@angular/core'; import { BaseChartDirective } from 'ng2-charts'; - +import {Chart} from 'chart.js'; @Component({ selector: 'app-line-chart', templateUrl: './line-chart.component.html', styleUrls: ['./line-chart.component.css'] }) -export class LineChartComponent implements OnInit { +export class LineChartComponent implements OnInit { + @Input() dataAcc=[] ; + @Input() dataEpoch=[]; constructor() { } ngOnInit(): void { - } - lineChartData:Array<any> = [ - {data: [65, 59, 80, 81, 56, 55, 40], label: 'Series A'}, - {data: [28, 48, 40, 19, 86, 27, 90], label: 'Series B'}, - {data: [18, 48, 77, 9, 100, 27, 40], label: 'Series C'} - ]; - lineChartLabels: BaseChartDirective["labels"] = ['January', 'February', 'March', 'April', 'May', 'June']; - lineChartOptions = { - responsive: true, - }; - lineChartColors:Array<any> = [ - { // grey - backgroundColor: 'rgba(148,159,177,0.2)', - borderColor: 'rgba(148,159,177,1)', - pointBackgroundColor: 'rgba(148,159,177,1)', - pointBorderColor: '#fff', - pointHoverBackgroundColor: '#fff', - pointHoverBorderColor: 'rgba(148,159,177,0.8)' + var myChart=new Chart("myChart", + { + type: 'line', + data: { + labels:this.dataEpoch, + datasets: [{ + label: 'Vrednost', + data: this.dataAcc, + borderWidth: 1 + }] }, - { // dark grey - backgroundColor: 'rgba(77,83,96,0.2)', - borderColor: 'rgba(77,83,96,1)', - pointBackgroundColor: 'rgba(77,83,96,1)', - pointBorderColor: '#fff', - pointHoverBackgroundColor: '#fff', - pointHoverBorderColor: 'rgba(77,83,96,1)' - }, - { // grey - backgroundColor: 'rgba(148,159,177,0.2)', - borderColor: 'rgba(148,159,177,1)', - pointBackgroundColor: 'rgba(148,159,177,1)', - pointBorderColor: '#fff', - pointHoverBackgroundColor: '#fff', - pointHoverBorderColor: 'rgba(148,159,177,0.8)' + options: { + scales: { + y: { + beginAtZero: true + } + } } - ]; - lineChartLegend = true; - lineChartPlugins = []; - lineChartType = 'line'; - + } + ); + + } } - - +
\ No newline at end of file diff --git a/frontend/src/app/_elements/metric-view/metric-view.component.css b/frontend/src/app/_elements/metric-view/metric-view.component.css new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/frontend/src/app/_elements/metric-view/metric-view.component.css diff --git a/frontend/src/app/_elements/metric-view/metric-view.component.html b/frontend/src/app/_elements/metric-view/metric-view.component.html new file mode 100644 index 00000000..7408547a --- /dev/null +++ b/frontend/src/app/_elements/metric-view/metric-view.component.html @@ -0,0 +1,5 @@ +<div> + <app-line-chart [data]="myAcc"> + + </app-line-chart> +</div> diff --git a/frontend/src/app/_elements/metric-view/metric-view.component.spec.ts b/frontend/src/app/_elements/metric-view/metric-view.component.spec.ts new file mode 100644 index 00000000..c3ecc67f --- /dev/null +++ b/frontend/src/app/_elements/metric-view/metric-view.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MetricViewComponent } from './metric-view.component'; + +describe('MetricViewComponent', () => { + let component: MetricViewComponent; + let fixture: ComponentFixture<MetricViewComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ MetricViewComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(MetricViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/_elements/metric-view/metric-view.component.ts b/frontend/src/app/_elements/metric-view/metric-view.component.ts new file mode 100644 index 00000000..76dd7d20 --- /dev/null +++ b/frontend/src/app/_elements/metric-view/metric-view.component.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from '@angular/core'; +import { SignalRService } from 'src/app/_services/signal-r.service'; +@Component({ + selector: 'app-metric-view', + templateUrl: './metric-view.component.html', + styleUrls: ['./metric-view.component.css'] +}) +export class MetricViewComponent implements OnInit { + myAcc:[]=[]; + myMae:[]=[]; + myMse:[]=[]; + myEpochs:[]=[]; + constructor(private signalRService: SignalRService) { } + + ngOnInit(): void { + if(this.signalRService.hubConnection) + { + this.signalRService.hubConnection.on("NotifyEpoch", (mName: string, mId: string, stat: string, totalEpochs: number, currentEpoch: number) => { + console.log(stat) + console.log(totalEpochs) + const data=JSON.parse(stat) + for (let key in data) + { + let value = data[key]; + console.log(value) + } + }); + + } + + } +} diff --git a/frontend/src/app/_elements/model-load/model-load.component.ts b/frontend/src/app/_elements/model-load/model-load.component.ts index 5f9caf9d..8bf8fd93 100644 --- a/frontend/src/app/_elements/model-load/model-load.component.ts +++ b/frontend/src/app/_elements/model-load/model-load.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit, ViewChild, Output, EventEmitter, Input } from '@angu 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 { AuthService } from 'src/app/_services/auth.service'; import { ModelsService } from 'src/app/_services/models.service'; import { GraphComponent } from '../graph/graph.component'; @@ -14,7 +15,7 @@ import { GraphComponent } from '../graph/graph.component'; export class ModelLoadComponent implements OnInit { @ViewChild(GraphComponent) graph!: GraphComponent; - @Input() forExperiment?:Experiment; + @Input() forExperiment?: Experiment; @Output() selectedModelChangeEvent = new EventEmitter<Model>(); newModel: Model = new Model(); @@ -38,13 +39,20 @@ export class ModelLoadComponent implements OnInit { batchSizePower: number = 2; - constructor(private modelsService: ModelsService) { + constructor(private modelsService: ModelsService, private authService: AuthService) { //console.log("forExperiment = ", this.forExperiment); - + this.fetchModels(); + + this.authService.loggedInEvent.subscribe(_ => { + this.fetchModels(); + }) + } + + fetchModels() { //if (this.forExperiment == undefined) { - this.modelsService.getMyModels().subscribe((models) => { - this.myModels = models; - }); + this.modelsService.getMyModels().subscribe((models) => { + this.myModels = models; + }); /*} else { this.modelsService.getMyModelsByType(ProblemType.Regression).subscribe((models) => { @@ -56,10 +64,9 @@ export class ModelLoadComponent implements OnInit { ngOnInit(): void { } - - updateBatchSize() - { - this.newModel.batchSize=2**this.batchSizePower; + + updateBatchSize() { + this.newModel.batchSize = 2 ** this.batchSizePower; } updateGraph() { diff --git a/frontend/src/app/_elements/navbar/navbar.component.html b/frontend/src/app/_elements/navbar/navbar.component.html index 7d0c4cd8..1988b834 100644 --- a/frontend/src/app/_elements/navbar/navbar.component.html +++ b/frontend/src/app/_elements/navbar/navbar.component.html @@ -6,31 +6,25 @@ </a> <ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0"> - <li><a routerLink="" class="nav-link px-2" - [class]="(currentUrl === '') ? 'text-secondary' : 'text-white'">Početna</a></li> - <li><a routerLink="experiment" class="nav-link px-2" - [class]="(currentUrl === '/experiment') ? 'text-secondary' : 'text-white'">Napravi eksperiment</a> + <li><a routerLink="" class="nav-link px-2" [class]="(currentUrl === '') ? 'text-secondary' : 'text-white'">Početna</a></li> + <li><a routerLink="experiment" class="nav-link px-2" [class]="(currentUrl === '/experiment') ? 'text-secondary' : 'text-white'">Napravi eksperiment</a> </li> - <li><a routerLink="training" class="nav-link px-2" - [class]="(currentUrl === '/training') ? 'text-secondary' : 'text-white'">Treniraj model</a> + <li><a routerLink="training" class="nav-link px-2" [class]="(currentUrl === '/training') ? 'text-secondary' : 'text-white'">Treniraj model</a> </li> - <li><a routerLink="my-predictors" class="nav-link px-2" - [class]="(currentUrl === '/my-predictors') ? 'text-secondary' : 'text-white' + (shared.loggedIn) ? '' : 'disabled'">Predvidi</a> + <li><a routerLink="my-predictors" class="nav-link px-2" [class]="(currentUrl === '/my-predictors') ? 'text-secondary' : 'text-white' + (shared.loggedIn) ? '' : 'disabled'">Predvidi</a> </li> </ul> <div *ngIf="shared.loggedIn" class="dropdown text-end"> - <a href="#" class="d-block link-light text-decoration-none dropdown-toggle" id="dropdownUser1" - data-bs-toggle="dropdown" aria-expanded="false"> - <img [src]="'/assets/profilePictures/'+ shared.photoId +'.png'" alt="mdo" width="32" height="32" - class="rounded-circle"> + <a href="#" class="d-block link-light text-decoration-none dropdown-toggle" id="dropdownUser1" data-bs-toggle="dropdown" aria-expanded="false"> + <img [src]="'/assets/profilePictures/'+ shared.photoId +'.png'" alt="mdo" width="32" height="32" class="rounded-circle"> </a> - <ul class="dropdown-menu text-small" aria-labelledby="dropdownUser1" - style="position: absolute; inset: 0px 0px auto auto; margin: 0px; transform: translate(0px, 34px);" - data-popper-placement="bottom-end"> - <li><a class="dropdown-item" routerLink="add-model">Nov model...</a></li> - <li><a class="dropdown-item" routerLink="settings">Podešavanja</a></li> + <ul class="dropdown-menu text-small" aria-labelledby="dropdownUser1" style="position: absolute; inset: 0px 0px auto auto; margin: 0px; transform: translate(0px, 34px);" data-popper-placement="bottom-end"> + <li><a class="dropdown-item" routerLink="my-datasets">Moji izvori podataka</a></li> + <li><a class="dropdown-item" routerLink="my-models">Moji modeli</a></li> + <li><a class="dropdown-item" routerLink="my-predictors">Moji prediktori</a></li> <li><a class="dropdown-item" routerLink="profile">Moj profil</a></li> + <li><a class="dropdown-item" routerLink="settings" disabled>Podešavanja</a></li> <li> <hr class="dropdown-divider"> </li> @@ -38,12 +32,10 @@ </ul> </div> <div *ngIf="!shared.loggedIn" class="dropdown text-end"> - <button type="button" mat-raised-button color="primary" class="mx-2" data-bs-toggle="modal" - data-bs-target="#modalForLogin"> + <button type="button" mat-raised-button color="primary" class="mx-2" data-bs-toggle="modal" data-bs-target="#modalForLogin"> Prijavi se </button> - <button type="button" mat-raised-button color="primary" data-bs-toggle="modal" - data-bs-target="#modalForRegister"> + <button type="button" mat-raised-button color="primary" data-bs-toggle="modal" data-bs-target="#modalForRegister"> Registruj se </button> </div> diff --git a/frontend/src/app/_pages/home/home.component.html b/frontend/src/app/_pages/home/home.component.html index 08f95a69..f5e94d27 100644 --- a/frontend/src/app/_pages/home/home.component.html +++ b/frontend/src/app/_pages/home/home.component.html @@ -53,4 +53,5 @@ <app-carousel [items]="publicPredictors" [type]="'Predictor'"> </app-carousel> <h3><a routerLink="browse-predictors">Pogledaj sve javne trenirane modele...</a></h3> + </div>
\ No newline at end of file diff --git a/frontend/src/app/_services/auth.service.ts b/frontend/src/app/_services/auth.service.ts index ef340684..9e3f9f2f 100644 --- a/frontend/src/app/_services/auth.service.ts +++ b/frontend/src/app/_services/auth.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { EventEmitter, Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { JwtHelperService } from '@auth0/angular-jwt'; import { CookieService } from 'ngx-cookie-service'; @@ -12,6 +12,8 @@ const jwtHelper = new JwtHelperService(); }) export class AuthService { + public loggedInEvent: EventEmitter<boolean> = new EventEmitter(); + shared = shared; constructor(private http: HttpClient, private cookie: CookieService) { } @@ -52,7 +54,7 @@ export class AuthService { var property = jwtHelper.decodeToken(this.cookie.get('token')); var username = property['name']; if (username != "") { - + this.refresher = setTimeout(() => { this.http.post(`${Configuration.settings.apiURL}/auth/renewJwt`, {}, { headers: this.authHeader(), responseType: 'text' }).subscribe((response) => { this.authenticate(response); @@ -81,6 +83,7 @@ export class AuthService { } this.cookie.set('token', token, exp); this.updateUser(); + this.loggedInEvent.emit(true); } updateUser() { diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 6a95bfe6..41aec3b5 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -49,8 +49,11 @@ import { ItemExperimentComponent } from './_elements/item-experiment/item-experi import { YesNoDialogComponent } from './_modals/yes-no-dialog/yes-no-dialog.component'; import { Configuration } from './configuration.service'; import { PointLinechartComponent } from './point-linechart/point-linechart.component'; +import { GraficiComponent } from './grafici/grafici.component'; +import { MixedChartComponent } from './mixed-chart/mixed-chart.component'; import { LineChartComponent } from './_elements/line-chart/line-chart.component'; +import { MetricViewComponent } from './_elements/metric-view/metric-view.component'; export function initializeApp(appConfig: Configuration) { return () => appConfig.load(); } @@ -89,9 +92,15 @@ export function initializeApp(appConfig: Configuration) { GraphComponent, TrainingComponent, ItemExperimentComponent, - YesNoDialogComponent, + YesNoDialogComponent, + LineChartComponent, PointLinechartComponent, - LineChartComponent + GraficiComponent, + MixedChartComponent, + LineChartComponent, + MetricViewComponent, + + ], imports: [ BrowserModule, diff --git a/frontend/src/app/grafici/grafici.component.css b/frontend/src/app/grafici/grafici.component.css new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/frontend/src/app/grafici/grafici.component.css diff --git a/frontend/src/app/grafici/grafici.component.html b/frontend/src/app/grafici/grafici.component.html new file mode 100644 index 00000000..5f987238 --- /dev/null +++ b/frontend/src/app/grafici/grafici.component.html @@ -0,0 +1 @@ +<p>grafici works!</p> diff --git a/frontend/src/app/grafici/grafici.component.spec.ts b/frontend/src/app/grafici/grafici.component.spec.ts new file mode 100644 index 00000000..9b5ba94d --- /dev/null +++ b/frontend/src/app/grafici/grafici.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GraficiComponent } from './grafici.component'; + +describe('GraficiComponent', () => { + let component: GraficiComponent; + let fixture: ComponentFixture<GraficiComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ GraficiComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(GraficiComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/grafici/grafici.component.ts b/frontend/src/app/grafici/grafici.component.ts new file mode 100644 index 00000000..749b35e2 --- /dev/null +++ b/frontend/src/app/grafici/grafici.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-grafici', + templateUrl: './grafici.component.html', + styleUrls: ['./grafici.component.css'] +}) +export class GraficiComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/frontend/src/app/mixed-chart/mixed-chart.component.css b/frontend/src/app/mixed-chart/mixed-chart.component.css new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/frontend/src/app/mixed-chart/mixed-chart.component.css diff --git a/frontend/src/app/mixed-chart/mixed-chart.component.html b/frontend/src/app/mixed-chart/mixed-chart.component.html new file mode 100644 index 00000000..806ea9e8 --- /dev/null +++ b/frontend/src/app/mixed-chart/mixed-chart.component.html @@ -0,0 +1,2 @@ +<canvas #mixedchart width="800" height="450"></canvas> +<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script> diff --git a/frontend/src/app/mixed-chart/mixed-chart.component.spec.ts b/frontend/src/app/mixed-chart/mixed-chart.component.spec.ts new file mode 100644 index 00000000..361cd047 --- /dev/null +++ b/frontend/src/app/mixed-chart/mixed-chart.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MixedChartComponent } from './mixed-chart.component'; + +describe('MixedChartComponent', () => { + let component: MixedChartComponent; + let fixture: ComponentFixture<MixedChartComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ MixedChartComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(MixedChartComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/mixed-chart/mixed-chart.component.ts b/frontend/src/app/mixed-chart/mixed-chart.component.ts new file mode 100644 index 00000000..2524ee36 --- /dev/null +++ b/frontend/src/app/mixed-chart/mixed-chart.component.ts @@ -0,0 +1,56 @@ +import { AfterViewInit, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; +import {Chart} from 'node_modules/chart.js'; + +@Component({ + selector: 'app-mixed-chart', + templateUrl: './mixed-chart.component.html', + styleUrls: ['./mixed-chart.component.css'] +}) +export class MixedChartComponent implements AfterViewInit { + + @ViewChild('mixedchart') chartRef!: ElementRef; + constructor() { } + + ngAfterViewInit(): void { + const myChart = new Chart(this.chartRef.nativeElement, { + type: 'bar', + data: { + labels: ["1900", "1950", "1999", "2050"], + datasets: [{ + label: "Europe", + type: "line", + borderColor: "#8e5ea2", + data: [408,547,675,734], + fill: false + }, { + label: "Africa", + type: "line", + borderColor: "#3e95cd", + data: [133,221,783,2478], + fill: false + }, { + label: "Europe", + type: "bar", + backgroundColor: "rgba(0,0,0,0.2)", + data: [408,547,675,734], + }, { + label: "Africa", + type: "bar", + backgroundColor: "rgba(0,0,0,0.2)", + //backgroundColorHover: "#3e95cd", + data: [133,221,783,2478] + } + ] + }, + /*options: { + title: { + display: true, + text: 'Population growth (millions): Europe & Africa' + }, + legend: { display: false } + }*/ + + }); + } + +} diff --git a/frontend/src/app/training/training.component.ts b/frontend/src/app/training/training.component.ts index cf5d44ea..4c38f166 100644 --- a/frontend/src/app/training/training.component.ts +++ b/frontend/src/app/training/training.component.ts @@ -4,15 +4,17 @@ import Shared from '../Shared'; import Experiment from '../_data/Experiment'; import Model, { ProblemType } from '../_data/Model'; import { ModelLoadComponent } from '../_elements/model-load/model-load.component'; +import { AuthService } from '../_services/auth.service'; import { ExperimentsService } from '../_services/experiments.service'; import { ModelsService } from '../_services/models.service'; +import { SignalRService } from '../_services/signal-r.service'; @Component({ selector: 'app-training', templateUrl: './training.component.html', styleUrls: ['./training.component.css'] }) -export class TrainingComponent implements OnInit{ +export class TrainingComponent implements OnInit { @ViewChild(ModelLoadComponent) modelLoadComponent?: ModelLoadComponent; @@ -24,22 +26,39 @@ export class TrainingComponent implements OnInit{ term: string = ""; - constructor(private modelsService: ModelsService, private route: ActivatedRoute, private experimentsService: ExperimentsService) { + constructor(private modelsService: ModelsService, private route: ActivatedRoute, private experimentsService: ExperimentsService, private authService: AuthService, private signalRService: SignalRService) { + if (this.signalRService.hubConnection) { + this.signalRService.hubConnection.on("NotifyEpoch", (mName: string, mId: string, stat: string, totalEpochs: number, currentEpoch: number) => { + if (this.selectedModel?._id == mId) { + this.trainingResult = stat; + } + }); + } } - ngOnInit(): void { + ngOnInit(): void { this.route.queryParams.subscribe(params => { - let experimentId =this.route.snapshot.paramMap.get("id"); + let experimentId = this.route.snapshot.paramMap.get("id"); - this.experimentsService.getMyExperiments().subscribe((experiments) => { - this.myExperiments = experiments; + this.fetchExperiments(experimentId); - this.selectedExperiment = this.myExperiments.filter(x => x._id == experimentId)[0]; - console.log("selektovan exp u training comp: ", this.selectedExperiment); + this.authService.loggedInEvent.subscribe(_ => { + this.fetchExperiments(experimentId); + + this.signalRService.startConnection() }); }); } + fetchExperiments(andSelectWithId: string | null = '') { + this.experimentsService.getMyExperiments().subscribe((experiments) => { + this.myExperiments = experiments; + + this.selectedExperiment = this.myExperiments.filter(x => x._id == andSelectWithId)[0]; + console.log("selektovan exp u training comp: ", this.selectedExperiment); + }); + } + selectThisExperiment(experiment: Experiment) { this.selectedExperiment = experiment; if (this.modelLoadComponent) |