From 19fd492a03ea48571d6aaab9e75108a82599ef0a Mon Sep 17 00:00:00 2001 From: Danijel Andjelkovic Date: Wed, 6 Apr 2022 13:07:23 +0200 Subject: Dodao klasu za notifikacije i dizajn. Dodao spinner u datatable komponentu. --- .../_elements/datatable/datatable.component.html | 46 ++++++------ .../app/_elements/datatable/datatable.component.ts | 2 + .../app/_elements/loading/loading.component.css | 81 ++++++++++++++++++++++ .../app/_elements/loading/loading.component.html | 11 +++ .../_elements/loading/loading.component.spec.ts | 25 +++++++ .../src/app/_elements/loading/loading.component.ts | 15 ++++ .../notifications/notifications.component.html | 23 +++++- .../notifications/notifications.component.ts | 12 +++- 8 files changed, 190 insertions(+), 25 deletions(-) create mode 100644 frontend/src/app/_elements/loading/loading.component.css create mode 100644 frontend/src/app/_elements/loading/loading.component.html create mode 100644 frontend/src/app/_elements/loading/loading.component.spec.ts create mode 100644 frontend/src/app/_elements/loading/loading.component.ts (limited to 'frontend/src/app/_elements') diff --git a/frontend/src/app/_elements/datatable/datatable.component.html b/frontend/src/app/_elements/datatable/datatable.component.html index bd9e7a13..8fcd44ac 100644 --- a/frontend/src/app/_elements/datatable/datatable.component.html +++ b/frontend/src/app/_elements/datatable/datatable.component.html @@ -1,25 +1,31 @@
-
- - - - - - - - - - - -
{{item}}
{{col}}
+
+
+ +
+
+ + + + + + + + + + + +
{{item}}
{{col}}
- - - - - - -
{{col}}
+ + + + + + +
{{col}}
+
diff --git a/frontend/src/app/_elements/datatable/datatable.component.ts b/frontend/src/app/_elements/datatable/datatable.component.ts index d3740d83..3343f6f0 100644 --- a/frontend/src/app/_elements/datatable/datatable.component.ts +++ b/frontend/src/app/_elements/datatable/datatable.component.ts @@ -11,6 +11,8 @@ export class DatatableComponent implements OnInit { @Input() data?: any[] = []; + loaded = false; + constructor() { } ngOnInit(): void { diff --git a/frontend/src/app/_elements/loading/loading.component.css b/frontend/src/app/_elements/loading/loading.component.css new file mode 100644 index 00000000..f39f60ee --- /dev/null +++ b/frontend/src/app/_elements/loading/loading.component.css @@ -0,0 +1,81 @@ +.lds-grid { + display: inline-block; + position: relative; + width: 80px; + height: 80px; +} + +.lds-grid div { + position: absolute; + width: 16px; + height: 16px; + border-radius: 50%; + background: #fff; + animation: lds-grid 1.2s linear infinite; +} + +.lds-grid div:nth-child(1) { + top: 8px; + left: 8px; + animation-delay: 0s; +} + +.lds-grid div:nth-child(2) { + top: 8px; + left: 32px; + animation-delay: -0.4s; +} + +.lds-grid div:nth-child(3) { + top: 8px; + left: 56px; + animation-delay: -0.8s; +} + +.lds-grid div:nth-child(4) { + top: 32px; + left: 8px; + animation-delay: -0.4s; +} + +.lds-grid div:nth-child(5) { + top: 32px; + left: 32px; + animation-delay: -0.8s; +} + +.lds-grid div:nth-child(6) { + top: 32px; + left: 56px; + animation-delay: -1.2s; +} + +.lds-grid div:nth-child(7) { + top: 56px; + left: 8px; + animation-delay: -0.8s; +} + +.lds-grid div:nth-child(8) { + top: 56px; + left: 32px; + animation-delay: -1.2s; +} + +.lds-grid div:nth-child(9) { + top: 56px; + left: 56px; + animation-delay: -1.6s; +} + +@keyframes lds-grid { + + 0%, + 100% { + opacity: 1; + } + + 50% { + opacity: 0.5; + } +} \ No newline at end of file diff --git a/frontend/src/app/_elements/loading/loading.component.html b/frontend/src/app/_elements/loading/loading.component.html new file mode 100644 index 00000000..d2c7b74e --- /dev/null +++ b/frontend/src/app/_elements/loading/loading.component.html @@ -0,0 +1,11 @@ +
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/frontend/src/app/_elements/loading/loading.component.spec.ts b/frontend/src/app/_elements/loading/loading.component.spec.ts new file mode 100644 index 00000000..7aacfad9 --- /dev/null +++ b/frontend/src/app/_elements/loading/loading.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LoadingComponent } from './loading.component'; + +describe('LoadingComponent', () => { + let component: LoadingComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ LoadingComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(LoadingComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/_elements/loading/loading.component.ts b/frontend/src/app/_elements/loading/loading.component.ts new file mode 100644 index 00000000..4dff0cdf --- /dev/null +++ b/frontend/src/app/_elements/loading/loading.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-loading', + templateUrl: './loading.component.html', + styleUrls: ['./loading.component.css'] +}) +export class LoadingComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/frontend/src/app/_elements/notifications/notifications.component.html b/frontend/src/app/_elements/notifications/notifications.component.html index d1da41b4..0b87e4fc 100644 --- a/frontend/src/app/_elements/notifications/notifications.component.html +++ b/frontend/src/app/_elements/notifications/notifications.component.html @@ -1,3 +1,20 @@ -
-

Notifikacije

-
\ No newline at end of file +
+

Notifikacije + +

+ +
+
+
+

{{notification.title}}

+
+
+
+
+
+
+
\ No newline at end of file diff --git a/frontend/src/app/_elements/notifications/notifications.component.ts b/frontend/src/app/_elements/notifications/notifications.component.ts index 6c1d555b..82613448 100644 --- a/frontend/src/app/_elements/notifications/notifications.component.ts +++ b/frontend/src/app/_elements/notifications/notifications.component.ts @@ -1,5 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { WebSocketService } from 'src/app/_services/web-socket.service'; +import Notification from 'src/app/_data/Notification'; @Component({ selector: 'app-notifications', @@ -8,9 +9,16 @@ import { WebSocketService } from 'src/app/_services/web-socket.service'; }) export class NotificationsComponent implements OnInit { - notifications?: any[]; + notifications?: Notification[]; + closed: boolean = false; - constructor(private wsService: WebSocketService) { } + constructor(private wsService: WebSocketService) { + this.notifications = [ + new Notification("Titanik (Preziveli)", "79768456867", 0.2), + new Notification("Test Prediktor 1", "56758768678", 0.4), + new Notification("Test Prediktor 2", "11344556425", 0.7) + ] + } ngOnInit(): void { // this.wsService.send('test'); -- cgit v1.2.3 From af3333a77e254b3268de38ec397921b43f357949 Mon Sep 17 00:00:00 2001 From: Danijel Andjelkovic Date: Wed, 6 Apr 2022 13:08:32 +0200 Subject: Dodao stranicu za eksperimente, ova stranica je zamena za add-model stranicu. --- frontend/src/app/_data/Experiment.ts | 12 +++ frontend/src/app/_data/Model.ts | 41 ++++---- .../app/_elements/annvisual/annvisual.component.ts | 3 +- .../_elements/model-load/model-load.component.css | 0 .../_elements/model-load/model-load.component.html | 1 + .../model-load/model-load.component.spec.ts | 25 +++++ .../_elements/model-load/model-load.component.ts | 15 +++ .../src/app/_elements/navbar/navbar.component.html | 8 +- .../app/_pages/add-model/add-model.component.html | 29 +----- .../app/_pages/add-model/add-model.component.ts | 104 ++++++++++----------- frontend/src/app/app-routing.module.ts | 5 +- frontend/src/app/app.module.ts | 8 +- .../src/app/experiment/experiment.component.css | 39 ++++++++ .../src/app/experiment/experiment.component.html | 13 +++ .../app/experiment/experiment.component.spec.ts | 25 +++++ .../src/app/experiment/experiment.component.ts | 15 +++ 16 files changed, 233 insertions(+), 110 deletions(-) create mode 100644 frontend/src/app/_data/Experiment.ts create mode 100644 frontend/src/app/_elements/model-load/model-load.component.css create mode 100644 frontend/src/app/_elements/model-load/model-load.component.html create mode 100644 frontend/src/app/_elements/model-load/model-load.component.spec.ts create mode 100644 frontend/src/app/_elements/model-load/model-load.component.ts create mode 100644 frontend/src/app/experiment/experiment.component.css create mode 100644 frontend/src/app/experiment/experiment.component.html create mode 100644 frontend/src/app/experiment/experiment.component.spec.ts create mode 100644 frontend/src/app/experiment/experiment.component.ts (limited to 'frontend/src/app/_elements') diff --git a/frontend/src/app/_data/Experiment.ts b/frontend/src/app/_data/Experiment.ts new file mode 100644 index 00000000..706231c7 --- /dev/null +++ b/frontend/src/app/_data/Experiment.ts @@ -0,0 +1,12 @@ +export default class Experiment { + _id: string = ''; + constructor( + public name: string = 'Novi experiment', + public description: string = '', + public datasetId: string = '', + public inputColumns: string[] = [], + public columnToPredict: string = '', + public dateCreated: Date = new Date(), + public lastUpdated: Date = new Date() + ) { } +} \ No newline at end of file diff --git a/frontend/src/app/_data/Model.ts b/frontend/src/app/_data/Model.ts index 58bc3d4f..1ad4fc6d 100644 --- a/frontend/src/app/_data/Model.ts +++ b/frontend/src/app/_data/Model.ts @@ -7,11 +7,9 @@ export default class Model { public description: string = '', public dateCreated: Date = new Date(), public lastUpdated: Date = new Date(), - public datasetId: string = '', + public experimentId: string = '', // Test set settings - public inputColumns: string[] = [], - public columnToPredict: string = '', public randomOrder: boolean = true, public randomTestSet: boolean = true, public randomTestSetDistribution: number = 0.1, //0.1-0.9 (10% - 90%) JESTE OVDE ZAKUCANO 10, AL POSLATO JE KAO 0.1 BACK-U @@ -168,31 +166,28 @@ export enum Metrics { MSE = 'mse', MAE = 'mae', RMSE = 'rmse' - + } -export enum MetricsRegression -{ +export enum MetricsRegression { Mse = 'mse', Mae = 'mae', Mape = 'mape', - Msle='msle', - CosineProximity='cosine' + Msle = 'msle', + CosineProximity = 'cosine' } -export enum MetricsBinaryClassification -{ - Accuracy='binary_accuracy', - Auc="AUC", - Precision='precision_score', - Recall='recall_score', - F1='f1_score', - +export enum MetricsBinaryClassification { + Accuracy = 'binary_accuracy', + Auc = "AUC", + Precision = 'precision_score', + Recall = 'recall_score', + F1 = 'f1_score', + } -export enum MetricsMultiClassification -{ - Accuracy='categorical_accuracy', - Auc="AUC", - Precision='precision_score', - Recall='recall_score', - F1='f1_score', +export enum MetricsMultiClassification { + Accuracy = 'categorical_accuracy', + Auc = "AUC", + Precision = 'precision_score', + Recall = 'recall_score', + F1 = 'f1_score', } diff --git a/frontend/src/app/_elements/annvisual/annvisual.component.ts b/frontend/src/app/_elements/annvisual/annvisual.component.ts index 53e4e2ca..df0a3898 100644 --- a/frontend/src/app/_elements/annvisual/annvisual.component.ts +++ b/frontend/src/app/_elements/annvisual/annvisual.component.ts @@ -18,7 +18,7 @@ export class AnnvisualComponent implements OnInit { let hiddenlayerstring: string = ''; let digraphstring: string = 'digraph {'; - for (let i = 0; i < this.model.inputColumns.length; i++) { + for (let i = 0; i < /*this.model.inputColumns.length*/ 10; i++) { inputlayerstring = inputlayerstring + 'i' + i + ','; } inputlayerstring = inputlayerstring.slice(0, -1); @@ -35,7 +35,6 @@ export class AnnvisualComponent implements OnInit { } digraphstring = digraphstring + 'o}'; - graphviz('#graph').renderDot(digraphstring); } diff --git a/frontend/src/app/_elements/model-load/model-load.component.css b/frontend/src/app/_elements/model-load/model-load.component.css new file mode 100644 index 00000000..e69de29b 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..ced9b0d6 --- /dev/null +++ b/frontend/src/app/_elements/model-load/model-load.component.html @@ -0,0 +1 @@ +

model-load works!

diff --git a/frontend/src/app/_elements/model-load/model-load.component.spec.ts b/frontend/src/app/_elements/model-load/model-load.component.spec.ts new file mode 100644 index 00000000..1dafd966 --- /dev/null +++ b/frontend/src/app/_elements/model-load/model-load.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ModelLoadComponent } from './model-load.component'; + +describe('ModelLoadComponent', () => { + let component: ModelLoadComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ModelLoadComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ModelLoadComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); 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..00532bea --- /dev/null +++ b/frontend/src/app/_elements/model-load/model-load.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-model-load', + templateUrl: './model-load.component.html', + styleUrls: ['./model-load.component.css'] +}) +export class ModelLoadComponent implements OnInit { + + constructor() { } + + ngOnInit(): void { + } + +} diff --git a/frontend/src/app/_elements/navbar/navbar.component.html b/frontend/src/app/_elements/navbar/navbar.component.html index 82a1ea07..dbee4773 100644 --- a/frontend/src/app/_elements/navbar/navbar.component.html +++ b/frontend/src/app/_elements/navbar/navbar.component.html @@ -8,8 +8,9 @@
- - + @@ -38,4 +38,12 @@
-
\ No newline at end of file +
+ +
+ +
+ +
+ +
diff --git a/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.ts b/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.ts index fceb53cf..c5e6558a 100644 --- a/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.ts +++ b/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.ts @@ -1,6 +1,10 @@ import { Component, EventEmitter, Output, ViewChild } from '@angular/core'; import { NgxCsvParser, NgxCSVParserError } from 'ngx-csv-parser'; import Dataset from 'src/app/_data/Dataset'; +import { DatasetsService } from 'src/app/_services/datasets.service'; +import { ModelsService } from 'src/app/_services/models.service'; +import shared from 'src/app/Shared'; +import { DatatableComponent } from '../datatable/datatable.component'; @Component({ selector: 'app-add-new-dataset', @@ -9,7 +13,8 @@ import Dataset from 'src/app/_data/Dataset'; }) export class AddNewDatasetComponent { - @Output() loaded = new EventEmitter(); + @Output() newDatasetAdded = new EventEmitter(); + @ViewChild(DatatableComponent) datatable?: DatatableComponent; delimiterOptions: Array = [",", ";", "\t", "razmak", "|"]; //podrazumevano "," @@ -23,7 +28,7 @@ export class AddNewDatasetComponent { dataset: Dataset; //dodaj ! potencijalno - constructor(private ngxCsvParser: NgxCsvParser) { + constructor(private ngxCsvParser: NgxCsvParser, private modelsService: ModelsService, private datasetsService: DatasetsService) { this.dataset = new Dataset(); } @@ -48,6 +53,9 @@ export class AddNewDatasetComponent { if (this.files.length < 1) return; + this.datatable!.loaded = false; + this.datatable!.hasInput = this.hasInput; + this.ngxCsvParser.parse(this.files[0], { header: false, delimiter: (this.dataset.delimiter == "razmak") ? " " : (this.dataset.delimiter == "") ? "," : this.dataset.delimiter }) .pipe().subscribe((result) => { @@ -60,10 +68,12 @@ export class AddNewDatasetComponent { this.rowsNumber = this.csvRecords.length; this.colsNumber = this.csvRecords[0].length; - if (this.dataset.hasHeader) //kasnije dodati opciju kada nema header da korisnik rucno unosi header-e + if (this.dataset.hasHeader) this.dataset.header = this.csvRecords[0]; - - this.loaded.emit("loaded"); + + this.datatable!.data = this.csvRecords; + this.datatable!.hasHeader = this.dataset.hasHeader; + this.datatable!.loaded = true; } }, (error: NgxCSVParserError) => { console.log('Error', error); @@ -75,4 +85,26 @@ export class AddNewDatasetComponent { this.dataset.accessibleByLink = true; } + uploadDataset() { + this.modelsService.uploadData(this.files[0]).subscribe((file) => { + //console.log('ADD MODEL: STEP 2 - ADD DATASET WITH FILE ID ' + file._id); + this.dataset.fileId = file._id; + this.dataset.username = shared.username; + + this.datasetsService.addDataset(this.dataset).subscribe((dataset) => { + + this.newDatasetAdded.emit("added"); + //this.refreshMyDatasetList(); refreshuj dataset listu u ds-load i selektuj taj ds + //this.showMyDatasets = true; + //this.selectThisDataset(dataset); + + shared.openDialog("Obaveštenje", "Uspešno ste dodali novi izvor podataka u kolekciju. Molimo sačekajte par trenutaka da se procesira."); + }, (error) => { + shared.openDialog("Neuspeo pokušaj!", "Dataset sa unetim nazivom već postoji u Vašoj kolekciji. Izmenite naziv ili iskoristite postojeći dataset."); + }); //kraj addDataset subscribe + }, (error) => { + + }); //kraj uploadData subscribe + } + } diff --git a/frontend/src/app/_elements/dataset-load/dataset-load.component.html b/frontend/src/app/_elements/dataset-load/dataset-load.component.html index 674e5990..2052c9b5 100644 --- a/frontend/src/app/_elements/dataset-load/dataset-load.component.html +++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.html @@ -3,8 +3,7 @@
-

Izvor podataka:

-
+
-
    -
  • - -
  • -
+
    +
  • + +
  • +
+
+ +
+ (newDatasetAdded)="showMyDatasets = true"> -
- -
\ No newline at end of file diff --git a/frontend/src/app/_elements/datatable/datatable.component.html b/frontend/src/app/_elements/datatable/datatable.component.html index 8fcd44ac..52d50443 100644 --- a/frontend/src/app/_elements/datatable/datatable.component.html +++ b/frontend/src/app/_elements/datatable/datatable.component.html @@ -1,11 +1,11 @@ -
+
- +
@@ -18,7 +18,7 @@
{{item}}
- +
@@ -28,7 +28,7 @@ -
+

{{data.length - 1}} x {{data[0].length}} {{data.length}} x {{data[0].length}} diff --git a/frontend/src/app/_elements/datatable/datatable.component.ts b/frontend/src/app/_elements/datatable/datatable.component.ts index 3343f6f0..19fb204e 100644 --- a/frontend/src/app/_elements/datatable/datatable.component.ts +++ b/frontend/src/app/_elements/datatable/datatable.component.ts @@ -11,6 +11,7 @@ export class DatatableComponent implements OnInit { @Input() data?: any[] = []; + hasInput = false; loaded = false; constructor() { } diff --git a/frontend/src/app/_services/auth.service.ts b/frontend/src/app/_services/auth.service.ts index ccfbe15f..a108f8db 100644 --- a/frontend/src/app/_services/auth.service.ts +++ b/frontend/src/app/_services/auth.service.ts @@ -33,6 +33,7 @@ export class AuthService { var token = this.cookie.get('token'); var property=jwtHelper.decodeToken(this.cookie.get('token')); var username=property['name']; + var userId = property['id']; return !jwtHelper.isTokenExpired(token) && username!=""; } return false; @@ -89,6 +90,7 @@ export class AuthService { console.log("decoded:", decodedToken); this.shared.loggedIn = this.isAuthenticated(); this.shared.username = decodedToken.name; + this.shared.userId = decodedToken.id; this.enableAutoRefresh(); } } -- cgit v1.2.3
{{col}}