aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/app
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/app')
-rw-r--r--frontend/src/app/Shared.ts7
-rw-r--r--frontend/src/app/_data/Dataset.ts13
-rw-r--r--frontend/src/app/_data/Model.ts12
-rw-r--r--frontend/src/app/_data/Predictor.ts11
-rw-r--r--frontend/src/app/_elements/carousel/carousel.component.css (renamed from frontend/src/app/_pages/login-page/login-page.component.css)0
-rw-r--r--frontend/src/app/_elements/carousel/carousel.component.html14
-rw-r--r--frontend/src/app/_elements/carousel/carousel.component.spec.ts (renamed from frontend/src/app/_pages/login-page/login-page.component.spec.ts)12
-rw-r--r--frontend/src/app/_elements/carousel/carousel.component.ts17
-rw-r--r--frontend/src/app/_elements/dataset-load/dataset-load.component.css6
-rw-r--r--frontend/src/app/_elements/dataset-load/dataset-load.component.html79
-rw-r--r--frontend/src/app/_elements/dataset-load/dataset-load.component.ts15
-rw-r--r--frontend/src/app/_elements/item-dataset/item-dataset.component.css (renamed from frontend/src/app/_pages/only-authorized/only-authorized.component.css)0
-rw-r--r--frontend/src/app/_elements/item-dataset/item-dataset.component.html15
-rw-r--r--frontend/src/app/_elements/item-dataset/item-dataset.component.spec.ts25
-rw-r--r--frontend/src/app/_elements/item-dataset/item-dataset.component.ts15
-rw-r--r--frontend/src/app/_elements/item-predictor/item-predictor.component.css (renamed from frontend/src/app/_pages/register-page/register-page.component.css)0
-rw-r--r--frontend/src/app/_elements/item-predictor/item-predictor.component.html24
-rw-r--r--frontend/src/app/_elements/item-predictor/item-predictor.component.spec.ts25
-rw-r--r--frontend/src/app/_elements/item-predictor/item-predictor.component.ts18
-rw-r--r--frontend/src/app/_elements/navbar/navbar.component.css0
-rw-r--r--frontend/src/app/_elements/navbar/navbar.component.html49
-rw-r--r--frontend/src/app/_elements/navbar/navbar.component.spec.ts25
-rw-r--r--frontend/src/app/_elements/navbar/navbar.component.ts30
-rw-r--r--frontend/src/app/_modals/login-modal/login-modal.component.html19
-rw-r--r--frontend/src/app/_modals/login-modal/login-modal.component.ts34
-rw-r--r--frontend/src/app/_modals/register-modal/register-modal.component.css0
-rw-r--r--frontend/src/app/_modals/register-modal/register-modal.component.html88
-rw-r--r--frontend/src/app/_modals/register-modal/register-modal.component.spec.ts25
-rw-r--r--frontend/src/app/_modals/register-modal/register-modal.component.ts (renamed from frontend/src/app/_pages/register-page/register-page.component.ts)67
-rw-r--r--frontend/src/app/_pages/add-model/add-model.component.css18
-rw-r--r--frontend/src/app/_pages/add-model/add-model.component.html402
-rw-r--r--frontend/src/app/_pages/add-model/add-model.component.ts72
-rw-r--r--frontend/src/app/_pages/browse-datasets/browse-datasets.component.css0
-rw-r--r--frontend/src/app/_pages/browse-datasets/browse-datasets.component.html1
-rw-r--r--frontend/src/app/_pages/browse-datasets/browse-datasets.component.spec.ts (renamed from frontend/src/app/_pages/only-authorized/only-authorized.component.spec.ts)12
-rw-r--r--frontend/src/app/_pages/browse-datasets/browse-datasets.component.ts15
-rw-r--r--frontend/src/app/_pages/browse-predictors/browse-predictors.component.css0
-rw-r--r--frontend/src/app/_pages/browse-predictors/browse-predictors.component.html1
-rw-r--r--frontend/src/app/_pages/browse-predictors/browse-predictors.component.spec.ts25
-rw-r--r--frontend/src/app/_pages/browse-predictors/browse-predictors.component.ts15
-rw-r--r--frontend/src/app/_pages/home/home.component.css0
-rw-r--r--frontend/src/app/_pages/home/home.component.html53
-rw-r--r--frontend/src/app/_pages/home/home.component.spec.ts25
-rw-r--r--frontend/src/app/_pages/home/home.component.ts45
-rw-r--r--frontend/src/app/_pages/login-page/login-page.component.html55
-rw-r--r--frontend/src/app/_pages/login-page/login-page.component.ts63
-rw-r--r--frontend/src/app/_pages/my-datasets/my-datasets.component.css0
-rw-r--r--frontend/src/app/_pages/my-datasets/my-datasets.component.html1
-rw-r--r--frontend/src/app/_pages/my-datasets/my-datasets.component.spec.ts25
-rw-r--r--frontend/src/app/_pages/my-datasets/my-datasets.component.ts15
-rw-r--r--frontend/src/app/_pages/my-models/my-models.component.css0
-rw-r--r--frontend/src/app/_pages/my-models/my-models.component.html1
-rw-r--r--frontend/src/app/_pages/my-models/my-models.component.spec.ts25
-rw-r--r--frontend/src/app/_pages/my-models/my-models.component.ts15
-rw-r--r--frontend/src/app/_pages/my-predictors/my-predictors.component.css0
-rw-r--r--frontend/src/app/_pages/my-predictors/my-predictors.component.html1
-rw-r--r--frontend/src/app/_pages/my-predictors/my-predictors.component.spec.ts (renamed from frontend/src/app/_pages/register-page/register-page.component.spec.ts)12
-rw-r--r--frontend/src/app/_pages/my-predictors/my-predictors.component.ts15
-rw-r--r--frontend/src/app/_pages/only-authorized/only-authorized.component.html1
-rw-r--r--frontend/src/app/_pages/only-authorized/only-authorized.component.ts15
-rw-r--r--frontend/src/app/_pages/predict/predict.component.css0
-rw-r--r--frontend/src/app/_pages/predict/predict.component.html1
-rw-r--r--frontend/src/app/_pages/predict/predict.component.spec.ts25
-rw-r--r--frontend/src/app/_pages/predict/predict.component.ts15
-rw-r--r--frontend/src/app/_pages/profile/profile.component.css0
-rw-r--r--frontend/src/app/_pages/profile/profile.component.html1
-rw-r--r--frontend/src/app/_pages/profile/profile.component.spec.ts25
-rw-r--r--frontend/src/app/_pages/profile/profile.component.ts15
-rw-r--r--frontend/src/app/_pages/register-page/register-page.component.html80
-rw-r--r--frontend/src/app/_pages/settings/settings.component.css0
-rw-r--r--frontend/src/app/_pages/settings/settings.component.html1
-rw-r--r--frontend/src/app/_pages/settings/settings.component.spec.ts25
-rw-r--r--frontend/src/app/_pages/settings/settings.component.ts15
-rw-r--r--frontend/src/app/_services/auth-guard.service.ts2
-rw-r--r--frontend/src/app/_services/auth.service.ts48
-rw-r--r--frontend/src/app/_services/models.service.spec.ts16
-rw-r--r--frontend/src/app/_services/models.service.ts25
-rw-r--r--frontend/src/app/app-routing.module.ts27
-rw-r--r--frontend/src/app/app.component.html5
-rw-r--r--frontend/src/app/app.module.ts44
80 files changed, 1425 insertions, 518 deletions
diff --git a/frontend/src/app/Shared.ts b/frontend/src/app/Shared.ts
new file mode 100644
index 00000000..126dc846
--- /dev/null
+++ b/frontend/src/app/Shared.ts
@@ -0,0 +1,7 @@
+class Shared {
+ constructor(
+ public loggedIn: boolean
+ ) { }
+}
+
+export default new Shared(false); \ No newline at end of file
diff --git a/frontend/src/app/_data/Dataset.ts b/frontend/src/app/_data/Dataset.ts
new file mode 100644
index 00000000..aaee50eb
--- /dev/null
+++ b/frontend/src/app/_data/Dataset.ts
@@ -0,0 +1,13 @@
+export default class Dataset {
+ constructor(
+ public name: string = 'Novi izvor podataka',
+ public description: string = '',
+ public header: string[] = [],
+ public fileId?: number,
+ public extension: string = '.csv',
+ public isPublic: boolean = false,
+ public accessibleByLink: boolean = false,
+ 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 216e1c36..c0bc339d 100644
--- a/frontend/src/app/_data/Model.ts
+++ b/frontend/src/app/_data/Model.ts
@@ -3,11 +3,13 @@ export default class Model {
public name: string = 'Novi model',
public description: string = '',
public dateCreated: Date = new Date(),
- public datasetId?: number,
+ public lastUpdated: Date = new Date(),
+ public datasetId: string = '',
- //Test set settings
- public inputColumns: number[] = [0],
- public columnToPredict: number = 1,
+ // Test set settings
+ public inputColumns: string[] = [],
+ public columnToPredict: string = '',
+ public randomOrder: boolean = true,
public randomTestSet: boolean = true,
public randomTestSetDistribution: number = 0.10, //0.1-0.9 (10% - 90%)
@@ -31,6 +33,8 @@ export enum ANNType {
Convolutional = 'konvoluciona'
}
+// replaceMissing srednja vrednost mean, median, najcesca vrednost (mode)
+// removeOutliers
export enum Encoding {
Label = 'label',
OneHot = 'one hot'
diff --git a/frontend/src/app/_data/Predictor.ts b/frontend/src/app/_data/Predictor.ts
new file mode 100644
index 00000000..05b993f1
--- /dev/null
+++ b/frontend/src/app/_data/Predictor.ts
@@ -0,0 +1,11 @@
+export default class Predictor {
+ constructor(
+ public name: string = 'Novi prediktor',
+ public description: string = '',
+ public inputs: string[] = [],
+ public output: string = '',
+ public isPublic: boolean = false,
+ public accessibleByLink: boolean = false,
+ public dateCreated: Date = new Date()
+ ) { }
+} \ No newline at end of file
diff --git a/frontend/src/app/_pages/login-page/login-page.component.css b/frontend/src/app/_elements/carousel/carousel.component.css
index e69de29b..e69de29b 100644
--- a/frontend/src/app/_pages/login-page/login-page.component.css
+++ b/frontend/src/app/_elements/carousel/carousel.component.css
diff --git a/frontend/src/app/_elements/carousel/carousel.component.html b/frontend/src/app/_elements/carousel/carousel.component.html
new file mode 100644
index 00000000..755899a7
--- /dev/null
+++ b/frontend/src/app/_elements/carousel/carousel.component.html
@@ -0,0 +1,14 @@
+<div class="container">
+ <div class="row d-flex align-items-stretch flex-row mx-5 align-items-stretch">
+ <div class="col my-1" *ngFor=" let item of items" [ngSwitch]="item.constructor.name">
+ <ng-template ngSwitchCase="Dataset">
+ <app-item-dataset [dataset]="item">
+ </app-item-dataset>
+ </ng-template>
+ <ng-template ngSwitchCase="Predictor">
+ <app-item-predictor [predictor]="item">
+ </app-item-predictor>
+ </ng-template>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_pages/login-page/login-page.component.spec.ts b/frontend/src/app/_elements/carousel/carousel.component.spec.ts
index 9da3aca8..9196e044 100644
--- a/frontend/src/app/_pages/login-page/login-page.component.spec.ts
+++ b/frontend/src/app/_elements/carousel/carousel.component.spec.ts
@@ -1,20 +1,20 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { LoginPageComponent } from './login-page.component';
+import { CarouselComponent } from './carousel.component';
-describe('LoginPageComponent', () => {
- let component: LoginPageComponent;
- let fixture: ComponentFixture<LoginPageComponent>;
+describe('CarouselComponent', () => {
+ let component: CarouselComponent;
+ let fixture: ComponentFixture<CarouselComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [ LoginPageComponent ]
+ declarations: [ CarouselComponent ]
})
.compileComponents();
});
beforeEach(() => {
- fixture = TestBed.createComponent(LoginPageComponent);
+ fixture = TestBed.createComponent(CarouselComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
diff --git a/frontend/src/app/_elements/carousel/carousel.component.ts b/frontend/src/app/_elements/carousel/carousel.component.ts
new file mode 100644
index 00000000..ed4fa4a5
--- /dev/null
+++ b/frontend/src/app/_elements/carousel/carousel.component.ts
@@ -0,0 +1,17 @@
+import { Component, Input, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-carousel',
+ templateUrl: './carousel.component.html',
+ styleUrls: ['./carousel.component.css']
+})
+export class CarouselComponent {
+
+ @Input() items: any[] = [];
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/frontend/src/app/_elements/dataset-load/dataset-load.component.css b/frontend/src/app/_elements/dataset-load/dataset-load.component.css
index e69de29b..05819702 100644
--- a/frontend/src/app/_elements/dataset-load/dataset-load.component.css
+++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.css
@@ -0,0 +1,6 @@
+#divInputs {
+ margin-left: 20px;
+}
+#divOutputs {
+ margin-left: 20px;
+} \ No newline at end of file
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 c89add43..fcec6ec3 100644
--- a/frontend/src/app/_elements/dataset-load/dataset-load.component.html
+++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.html
@@ -1,38 +1,57 @@
<div>
- <input style="display: inline-block; width:350px;" list=delimiterOptions
- placeholder="Izaberite ili ukucajte delimiter za .csv fajl" class="form-control" [(ngModel)]="delimiter"
- (input)="update()">
- <datalist id=delimiterOptions>
- <option *ngFor="let option of delimiterOptions">{{option}}</option>
- </datalist>
- &nbsp;&nbsp;&nbsp;&nbsp;
- <label for="checkboxHeader">Da li .csv ima header?</label> &nbsp;
- <input (input)="update()" [(ngModel)]="hasHeader" type="checkbox" value="" id="checkboxHeader" checked>
- <br><br>
+ <div class="row mb-4">
+ <div class="col-2">
+ </div>
+ <div class="col-3">
+ <label for="name" class="col-form-label">Naziv dataseta:</label>
+ <input type="text" class="form-control mb-3" name="name" placeholder="Naziv..."
+ [(ngModel)]="dataset.name">
+ <label for="desc" class="col-sm-2 col-form-label">Opis:</label>
+ <div>
+ <textarea class="form-control" name="desc" rows="3" [(ngModel)]="dataset.description"></textarea>
+ </div>
+ </div>
+ <div class="col-1">
+ </div>
+ <div class="col-4 mt-4">
+ <input list=delimiterOptions
+ placeholder="Izaberite ili ukucajte delimiter za .csv fajl" class="form-control mt-2" [(ngModel)]="delimiter"
+ (input)="update()">
+ <datalist id=delimiterOptions>
+ <option *ngFor="let option of delimiterOptions">{{option}}</option>
+ </datalist>
- <input id="fileInput" class="form-control mb-5" type="file" class="upload" (change)="changeListener($event)" accept=".csv">
+ <label for="type" class="form-check-label my-5">Da li .csv ima header?
+ <input class="mx-3 form-check-input" type="checkbox" (input)="update()" [(ngModel)]="hasHeader" type="checkbox" value="" id="checkboxHeader" checked>
+ </label>
+ <br>
+ <input id="fileInput" class="form-control" type="file" class="upload" (change)="changeListener($event)" accept=".csv">
+ </div>
+ </div>
- <table *ngIf="csvRecords.length > 0 && hasHeader" class="table table-bordered table-light mt-5">
- <thead>
- <tr>
- <th *ngFor="let item of csvRecords[0]; let i = index">{{item}}</th>
- </tr>
- </thead>
- <tbody>
- <tr *ngFor="let row of csvRecords | slice:1:11">
- <td *ngFor="let col of row">{{col}}</td>
- </tr>
- </tbody>
- </table>
+ <div class="table-responsive">
+ <table *ngIf="csvRecords.length > 0 && hasHeader" class="table table-bordered table-light mt-4">
+ <thead>
+ <tr>
+ <th *ngFor="let item of csvRecords[0]; let i = index">{{item}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let row of csvRecords | slice:1:11">
+ <td *ngFor="let col of row">{{col}}</td>
+ </tr>
+ </tbody>
+ </table>
- <table *ngIf="csvRecords.length > 0 && !hasHeader" class="table table-bordered table-light mt-5">
- <tbody>
- <tr *ngFor="let row of csvRecords | slice:0:10">
- <td *ngFor="let col of row">{{col}}</td>
- </tr>
- </tbody>
- </table>
+ <table *ngIf="csvRecords.length > 0 && !hasHeader" class="table table-bordered table-light mt-4">
+ <tbody>
+ <tr *ngFor="let row of csvRecords | slice:0:10">
+ <td *ngFor="let col of row">{{col}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
<div *ngIf="csvRecords.length > 0" id="info">
. . . <br>
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 843a5709..8465c3d6 100644
--- a/frontend/src/app/_elements/dataset-load/dataset-load.component.ts
+++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.ts
@@ -1,5 +1,6 @@
-import { Component, ViewChild } from '@angular/core';
+import { Component, EventEmitter, Output, ViewChild } from '@angular/core';
import { NgxCsvParser, NgxCSVParserError } from 'ngx-csv-parser';
+import Dataset from 'src/app/_data/Dataset';
@Component({
selector: 'app-dataset-load',
@@ -8,6 +9,8 @@ import { NgxCsvParser, NgxCSVParserError } from 'ngx-csv-parser';
})
export class DatasetLoadComponent {
+ @Output() loaded = new EventEmitter<string>();
+
delimiter: string = "";
delimiterOptions: Array<string> = [",", ";", "\t", "razmak", "|"]; //podrazumevano ","
@@ -20,7 +23,10 @@ export class DatasetLoadComponent {
rowsNumber: number = 0;
colsNumber: number = 0;
+ dataset: Dataset;
+
constructor(private ngxCsvParser: NgxCsvParser) {
+ this.dataset = new Dataset();
}
@ViewChild('fileImportInput', { static: false }) fileImportInput: any;
@@ -38,7 +44,7 @@ export class DatasetLoadComponent {
this.ngxCsvParser.parse(this.files[0], { header: false, delimiter: (this.delimiter == "razmak") ? " " : (this.delimiter == "") ? "," : this.delimiter})
.pipe().subscribe((result) => {
- //console.log('Result', result);
+ console.log('Result', result);
if (result.constructor === Array) {
this.csvRecords = result;
if (this.hasHeader)
@@ -46,9 +52,14 @@ export class DatasetLoadComponent {
else
this.rowsNumber = this.csvRecords.length;
this.colsNumber = this.csvRecords[0].length;
+
+ this.dataset.header = this.csvRecords[0];
+
+ this.loaded.emit("loaded");
}
}, (error: NgxCSVParserError) => {
console.log('Error', error);
});
}
+
}
diff --git a/frontend/src/app/_pages/only-authorized/only-authorized.component.css b/frontend/src/app/_elements/item-dataset/item-dataset.component.css
index e69de29b..e69de29b 100644
--- a/frontend/src/app/_pages/only-authorized/only-authorized.component.css
+++ b/frontend/src/app/_elements/item-dataset/item-dataset.component.css
diff --git a/frontend/src/app/_elements/item-dataset/item-dataset.component.html b/frontend/src/app/_elements/item-dataset/item-dataset.component.html
new file mode 100644
index 00000000..cf39a125
--- /dev/null
+++ b/frontend/src/app/_elements/item-dataset/item-dataset.component.html
@@ -0,0 +1,15 @@
+<div class="card" style="min-width: 12rem;">
+ <div class="card-header">
+ {{dataset.name}}
+ </div>
+ <div class="card-body">
+ <p class="card-text">
+ {{dataset.description}}
+ </p>
+ <table class="table table-bordered table-sm">
+ <thead>
+ <th scope="col" *ngFor="let column of dataset.header">{{column}}</th>
+ </thead>
+ </table>
+ </div>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_elements/item-dataset/item-dataset.component.spec.ts b/frontend/src/app/_elements/item-dataset/item-dataset.component.spec.ts
new file mode 100644
index 00000000..603889b2
--- /dev/null
+++ b/frontend/src/app/_elements/item-dataset/item-dataset.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ItemDatasetComponent } from './item-dataset.component';
+
+describe('ItemDatasetComponent', () => {
+ let component: ItemDatasetComponent;
+ let fixture: ComponentFixture<ItemDatasetComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ItemDatasetComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ItemDatasetComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_elements/item-dataset/item-dataset.component.ts b/frontend/src/app/_elements/item-dataset/item-dataset.component.ts
new file mode 100644
index 00000000..e12de34d
--- /dev/null
+++ b/frontend/src/app/_elements/item-dataset/item-dataset.component.ts
@@ -0,0 +1,15 @@
+import { Component, Input, OnInit } from '@angular/core';
+import Dataset from 'src/app/_data/Dataset';
+
+@Component({
+ selector: 'app-item-dataset',
+ templateUrl: './item-dataset.component.html',
+ styleUrls: ['./item-dataset.component.css']
+})
+export class ItemDatasetComponent {
+
+ @Input() dataset: Dataset = new Dataset();
+
+ constructor() {
+ }
+}
diff --git a/frontend/src/app/_pages/register-page/register-page.component.css b/frontend/src/app/_elements/item-predictor/item-predictor.component.css
index e69de29b..e69de29b 100644
--- a/frontend/src/app/_pages/register-page/register-page.component.css
+++ b/frontend/src/app/_elements/item-predictor/item-predictor.component.css
diff --git a/frontend/src/app/_elements/item-predictor/item-predictor.component.html b/frontend/src/app/_elements/item-predictor/item-predictor.component.html
new file mode 100644
index 00000000..92d747e2
--- /dev/null
+++ b/frontend/src/app/_elements/item-predictor/item-predictor.component.html
@@ -0,0 +1,24 @@
+<div class="card" style="min-width: 12rem;">
+ <div class="card-header">
+ {{predictor.name}}
+ </div>
+ <div class="card-body">
+ <p class="card-text">
+ {{predictor.description}}
+ </p>
+ <div class="d-flex flex-column align-items-center">
+ <table class="table table-bordered table-sm">
+ <thead>
+ <th class="text-center" *ngFor="let column of predictor.inputs">{{column}}</th>
+ </thead>
+ </table>
+ <mat-icon>arrow_downward</mat-icon>
+ <p>
+ {{predictor.output}}
+ </p>
+ </div>
+ </div>
+ <div class="card-footer text-center">
+ <a routerLink="predict" mat-raised-button color="primary">Iskoristi</a>
+ </div>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_elements/item-predictor/item-predictor.component.spec.ts b/frontend/src/app/_elements/item-predictor/item-predictor.component.spec.ts
new file mode 100644
index 00000000..b5c2d91c
--- /dev/null
+++ b/frontend/src/app/_elements/item-predictor/item-predictor.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ItemPredictorComponent } from './item-predictor.component';
+
+describe('ItemPredictorComponent', () => {
+ let component: ItemPredictorComponent;
+ let fixture: ComponentFixture<ItemPredictorComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ItemPredictorComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ItemPredictorComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_elements/item-predictor/item-predictor.component.ts b/frontend/src/app/_elements/item-predictor/item-predictor.component.ts
new file mode 100644
index 00000000..cc782f45
--- /dev/null
+++ b/frontend/src/app/_elements/item-predictor/item-predictor.component.ts
@@ -0,0 +1,18 @@
+import { Component, Input, OnInit } from '@angular/core';
+import Predictor from 'src/app/_data/Predictor';
+
+@Component({
+ selector: 'app-item-predictor',
+ templateUrl: './item-predictor.component.html',
+ styleUrls: ['./item-predictor.component.css']
+})
+export class ItemPredictorComponent implements OnInit {
+
+ @Input() predictor: Predictor = new Predictor();
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/frontend/src/app/_elements/navbar/navbar.component.css b/frontend/src/app/_elements/navbar/navbar.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_elements/navbar/navbar.component.css
diff --git a/frontend/src/app/_elements/navbar/navbar.component.html b/frontend/src/app/_elements/navbar/navbar.component.html
new file mode 100644
index 00000000..b9c450af
--- /dev/null
+++ b/frontend/src/app/_elements/navbar/navbar.component.html
@@ -0,0 +1,49 @@
+<header class="sticky-top p-3 bg-dark text-white">
+ <div class="container">
+ <div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
+ <a routerLink="" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
+ <img src="../../../assets/svg/logo_no_text.svg" class="bi me-2" width="64" height="40">
+ </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="add-model" class="nav-link px-2"
+ [class]="(currentUrl === '/add-model') ? 'text-secondary' : 'text-white'">Dodaj model</a></li>
+ <li><a routerLink="my-predictors" class="nav-link px-2"
+ [class]="(currentUrl === '/my-predictors') ? 'text-secondary' : 'text-white'">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="https://github.com/mdo.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>
+ <li><a class="dropdown-item" routerLink="profile">Moj profil</a></li>
+ <li>
+ <hr class="dropdown-divider">
+ </li>
+ <li><a class="dropdown-item" routerLink="" (click)="logOut()">Odjavi se</a></li>
+ </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">
+ Prijavi se
+ </button>
+ <button type="button" mat-raised-button color="primary" data-bs-toggle="modal"
+ data-bs-target="#modalForRegister">
+ Registruj se
+ </button>
+ </div>
+ </div>
+ </div>
+</header>
+
+<app-login-modal></app-login-modal>
+<app-register-modal></app-register-modal> \ No newline at end of file
diff --git a/frontend/src/app/_elements/navbar/navbar.component.spec.ts b/frontend/src/app/_elements/navbar/navbar.component.spec.ts
new file mode 100644
index 00000000..f8ccd6f4
--- /dev/null
+++ b/frontend/src/app/_elements/navbar/navbar.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { NavbarComponent } from './navbar.component';
+
+describe('NavbarComponent', () => {
+ let component: NavbarComponent;
+ let fixture: ComponentFixture<NavbarComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ NavbarComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(NavbarComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_elements/navbar/navbar.component.ts b/frontend/src/app/_elements/navbar/navbar.component.ts
new file mode 100644
index 00000000..c16e3e9d
--- /dev/null
+++ b/frontend/src/app/_elements/navbar/navbar.component.ts
@@ -0,0 +1,30 @@
+import { Component, OnInit } from '@angular/core';
+import { Location } from '@angular/common';
+import { AuthService } from '../../_services/auth.service';
+import shared from 'src/app/Shared';
+
+@Component({
+ selector: 'app-navbar',
+ templateUrl: './navbar.component.html',
+ styleUrls: ['./navbar.component.css']
+})
+export class NavbarComponent implements OnInit {
+
+ currentUrl: string;
+ shared = shared;
+
+ constructor(public location: Location, private auth: AuthService) {
+ this.currentUrl = this.location.path();
+ this.location.onUrlChange(() => {
+ this.currentUrl = this.location.path();
+ })
+ }
+
+ ngOnInit(): void {
+ this.auth.updateUser();
+ }
+
+ logOut() {
+ this.auth.logOut();
+ }
+}
diff --git a/frontend/src/app/_modals/login-modal/login-modal.component.html b/frontend/src/app/_modals/login-modal/login-modal.component.html
index 22f50de2..d694ea58 100644
--- a/frontend/src/app/_modals/login-modal/login-modal.component.html
+++ b/frontend/src/app/_modals/login-modal/login-modal.component.html
@@ -1,14 +1,9 @@
-<!-- Button trigger modal, OVO JE U STVARI DUGME U NAVBARU -->
-<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalForLogin" (click)="openModal()">
- Otvori login modal
-</button>
-
<!-- Modal -->
<div class="modal fade" id="modalForLogin" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
- <div class="modal-header bg-info">
- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+ <div class="modal-header" style="background-color: #003459;">
+ <button id="closeButton" type="button" class="btn-close" style="background-color:white;" data-bs-dismiss="modal" aria-label="Close" (click)="resetData()"></button>
</div>
<div class="modal-body px-5" style="color:#003459">
<h1 class="text-center mt-2 mb-4">Prijavite se</h1>
@@ -32,18 +27,16 @@
</div>
</form>
<div class="col-md-12 d-flex justify-content-center">
- <button type="button" class="btn btn-lg btn-info" style="color:white; border-color: #00a8e8; margin-right: 10px;" (click)="doLogin()">Prijavite se</button>
- <button type="button" class="btn btn-lg btn-outline-secondary" data-bs-dismiss="modal">Odustanite</button>
+ <button type="button" class="btn btn-lg" style="color:white; background-color: #003459; margin-right: 10px;" (click)="doLogin()">Prijavite se</button>
+ <button type="button" class="btn btn-lg btn-outline-secondary" data-bs-dismiss="modal" (click)="resetData()">Odustanite</button>
</div>
<br>
</div>
<div class="modal-footer justify-content-center">
<p class="small fw-bold">Još uvek nemate nalog?
- <a routerLink="/register" class="link-danger">Registrujte se</a>
+ <a data-bs-toggle="modal" data-bs-target="#modalForRegister" class="link-danger">Registrujte se</a>
</p>
</div>
</div>
</div>
-</div>
-
-
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_modals/login-modal/login-modal.component.ts b/frontend/src/app/_modals/login-modal/login-modal.component.ts
index 3a6fd8f1..d17d7017 100644
--- a/frontend/src/app/_modals/login-modal/login-modal.component.ts
+++ b/frontend/src/app/_modals/login-modal/login-modal.component.ts
@@ -1,11 +1,7 @@
import { Component, OnInit, ViewChild } from '@angular/core';
-import { FormControl, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { CookieService } from 'ngx-cookie-service';
import { AuthService } from 'src/app/_services/auth.service';
-import { ElementRef } from '@angular/core';
-
-declare var window: any;
@Component({
selector: 'app-login-modal',
@@ -14,7 +10,6 @@ declare var window: any;
})
export class LoginModalComponent implements OnInit {
- loginModal: any;
username: string = '';
password: string = '';
@@ -27,25 +22,22 @@ export class LoginModalComponent implements OnInit {
) { }
ngOnInit(): void {
- this.loginModal = new window.bootstrap.Modal(
- document.getElementById("modalForLogin")
- );
}
- openModal() {
- this.loginModal.show();
- //console.log("ok");
- //(<HTMLInputElement>document.getElementById("exampleModal")).style.display = "block";
- }
doLogin() {
- this.authService.login(this.username, this.password).subscribe((response) => { //ako nisu ok podaci, ne ide hide nego mora opet da ukucava!!!!podesi
- console.log(response);
- this.cookie.set('token', response);
- this.loginModal.hide(); //dodato
- this.router.navigate(['add-model']);
- });
- }
- sendToRegister() {
+ if (this.username.length > 0 && this.password.length > 0) {
+ this.authService.login(this.username, this.password).subscribe((response) => { //ako nisu ok podaci, ne ide hide nego mora opet da ukucava!!!!podesi
+ console.log(response);
+ this.authService.authenticate(response);
+ (<HTMLSelectElement>document.getElementById('closeButton')).click();
+ }, error => {
+ console.warn(error); //NETACNI PODACI
+ });
+ }
}
+ resetData() {
+ this.username = '';
+ this.password = '';
+ }
}
diff --git a/frontend/src/app/_modals/register-modal/register-modal.component.css b/frontend/src/app/_modals/register-modal/register-modal.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_modals/register-modal/register-modal.component.css
diff --git a/frontend/src/app/_modals/register-modal/register-modal.component.html b/frontend/src/app/_modals/register-modal/register-modal.component.html
new file mode 100644
index 00000000..7098c040
--- /dev/null
+++ b/frontend/src/app/_modals/register-modal/register-modal.component.html
@@ -0,0 +1,88 @@
+<!-- Modal -->
+<div class="modal fade" id="modalForRegister" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
+ aria-labelledby="staticBackdropLabel" aria-hidden="true">
+ <div class="modal-dialog modal-dialog-centered modal-dialog modal-lg">
+ <div class="modal-content">
+ <div class="modal-header" style="background-color: #003459;">
+ <button type="button" class="btn-close" data-bs-dismiss="modal" style="background-color: white;"
+ aria-label="Close" (click)="resetData()"></button>
+ </div>
+ <div class="modal-body" style="color:#003459">
+ <h1 class="text-center mt-2 mb-4">Registracija</h1>
+
+ <form class="mx-5">
+ <!--Ime-->
+ <div class="row">
+ <div class="col-6 px-3 py-3">
+ <label class="form-label" for="firstName">Ime</label>
+ <input type="text" id="firstName" class="form-control" [(ngModel)]="firstName"
+ name="firstName" placeholder="Unesite ime...">
+ <small *ngIf="wrongFirstNameBool" class="form-text text-danger">Unesite ispravno
+ ime.</small>
+ </div>
+ <!--Prezime-->
+ <div class="col-6 px-3 py-3">
+ <label class="form-label" for="lastName">Prezime</label>
+ <input type="text" id="lastName" class="form-control" [(ngModel)]="lastName" name="lastName"
+ placeholder="Unesite prezime..." />
+ <small *ngIf="wrongLastNameBool" class="form-text text-danger">Unesite ispravno
+ prezime.</small>
+ </div>
+ </div>
+ <div class="row">
+ <!--Korisnicko ime-->
+ <div class="col-12 px-3 py-3">
+ <label class="form-label" for="username-register">Korisničko ime</label>
+ <input type="text" id="username-register" class="form-control" [(ngModel)]="username"
+ name="username-register" placeholder="Unesite korisničko ime..." />
+ <small *ngIf="wrongUsernameBool" class="form-text text-danger">Unesite ispravno korisničko
+ ime.</small>
+ </div>
+ </div>
+ <div class="row">
+ <!--Email-->
+ <div class="col-12 px-3 py-3">
+ <label class="form-label" for="email">E-mail adresa</label>
+ <input type="email" id="email" class="form-control" [(ngModel)]="email" name="email"
+ placeholder="Unesite email adresu..." />
+ <small *ngIf="wrongEmailBool" class="form-text text-danger">Unesite ispravno e-mail
+ adresu.</small>
+ </div>
+ </div>
+ <div class="row">
+ <!-- Lozinka 1. -->
+ <div class="col-6 px-3 py-3">
+ <label class="form-label" for="pass1">Lozinka</label>
+ <input type="password" id="pass1" class="form-control" [(ngModel)]="pass1" name="pass1"
+ placeholder="Unesite lozinku..." />
+ <small *ngIf="wrongPass1Bool" class="form-text text-danger">Lozinka se mora sastojati od
+ najmanje 6 karaktera.</small>
+ </div>
+ <!-- Lozinka 2. -->
+ <div class="col-6 px-3 py-3">
+ <label class="form-label" for="pass2">Potvrdite lozinku</label>
+ <input type="password" id="pass2" class="form-control" [(ngModel)]="pass2" name="pass2"
+ placeholder="Ponovite lozinku..." />
+ <small *ngIf="wrongPass2Bool" class="form-text text-danger">Lozinke se ne
+ podudaraju.</small>
+ </div>
+ </div>
+ </form>
+ <div class="col-md-12 d-flex justify-content-center mt-5">
+ <button type="button" class="btn btn-lg"
+ style="color:white; background-color: #003459; margin-right: 10px;"
+ (click)="doRegister()">Registrujte se</button>
+ <button type="button" class="btn btn-lg btn-outline-secondary" style="margin-left: 15px;"
+ data-bs-dismiss="modal" (click)="resetData()">Odustanite</button>
+ </div>
+ <br>
+ </div>
+ <div class="modal-footer justify-content-center">
+ <p class="small fw-bold">Već imate kreiran nalog?
+ <a id="linkToLoginModal" data-bs-toggle="modal" data-bs-target="#modalForLogin"
+ class="link-danger">Prijavite se</a>
+ </p>
+ </div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_modals/register-modal/register-modal.component.spec.ts b/frontend/src/app/_modals/register-modal/register-modal.component.spec.ts
new file mode 100644
index 00000000..e371b3d8
--- /dev/null
+++ b/frontend/src/app/_modals/register-modal/register-modal.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { RegisterModalComponent } from './register-modal.component';
+
+describe('RegisterModalComponent', () => {
+ let component: RegisterModalComponent;
+ let fixture: ComponentFixture<RegisterModalComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ RegisterModalComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RegisterModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_pages/register-page/register-page.component.ts b/frontend/src/app/_modals/register-modal/register-modal.component.ts
index 712fc55e..c02a4e1a 100644
--- a/frontend/src/app/_pages/register-page/register-page.component.ts
+++ b/frontend/src/app/_modals/register-modal/register-modal.component.ts
@@ -1,45 +1,58 @@
import { Component, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
import { AuthService } from 'src/app/_services/auth.service';
@Component({
- selector: 'app-register-page',
- templateUrl: './register-page.component.html',
- styleUrls: ['./register-page.component.css']
+ selector: 'app-register-modal',
+ templateUrl: './register-modal.component.html',
+ styleUrls: ['./register-modal.component.css']
})
-export class RegisterPageComponent implements OnInit {
+export class RegisterModalComponent implements OnInit {
+
firstName: string = '';
lastName: string = '';
- nickName: string = '';
+ username: string = '';
email: string = '';
pass1: string = '';
pass2: string = '';
wrongFirstNameBool: boolean = false;
wrongLastNameBool: boolean = false;
- wrongNickNameBool: boolean = false;
+ wrongUsernameBool: boolean = false;
wrongEmailBool: boolean = false;
wrongPass1Bool: boolean = false;
wrongPass2Bool: boolean = false;
pattName: RegExp = /^[a-zA-ZšŠđĐčČćĆžŽ]+([ \-][a-zA-ZšŠđĐčČćĆžŽ]+)*$/;
+ pattUsername: RegExp = /^[a-zA-Z0-9]{6,18}$/;
pattTwoSpaces: RegExp = / /;
pattEmail: RegExp = /^[a-zA-Z0-9]+([\.\-\+][a-zA-Z0-9]+)*\@([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}$/;
pattPassword: RegExp = /.{6,30}$/;
constructor(
- private router: Router,
- private authService: AuthService,
+ private authService: AuthService
) { }
ngOnInit(): void {
}
+ doRegister() {
+ this.validation();
+ }
+ resetData() {
+ this.firstName = this.lastName = this.username = this.email = this.pass1 = this.pass2 = '';
+ this.wrongFirstNameBool = this.wrongLastNameBool = this.wrongUsernameBool = this.wrongEmailBool = this.wrongPass1Bool = this.wrongPass2Bool = false;
+ }
+
isCorrectName(element: string): boolean {
if (this.pattName.test(element) && !(this.pattTwoSpaces.test(element)) && (element.length >= 1 && element.length <= 30))
return true;
return false;
}
+ isCorrectUsername(element: string): boolean {
+ if (this.pattUsername.test(element) && !(this.pattTwoSpaces.test(element)) && (element.length >= 1 && element.length <= 30))
+ return true;
+ return false;
+ }
isCorrectEmail(element: string): boolean {
if (this.pattEmail.test(element.toLowerCase()) && element.length <= 320)
return true;
@@ -67,13 +80,13 @@ export class RegisterPageComponent implements OnInit {
(<HTMLSelectElement>document.getElementById('lastName')).focus();
this.wrongLastNameBool = true;
}
- nickNameValidation() {
- if (this.isCorrectName(this.nickName) == true) {
- this.wrongNickNameBool = false;
+ usernameValidation() {
+ if (this.isCorrectUsername(this.username) == true) {
+ this.wrongUsernameBool = false;
return;
}
- (<HTMLSelectElement>document.getElementById('nickName')).focus();
- this.wrongNickNameBool = true;
+ (<HTMLSelectElement>document.getElementById('username-register')).focus();
+ this.wrongUsernameBool = true;
}
emailValidation() {
if (this.isCorrectEmail(this.email) == true) {
@@ -99,22 +112,22 @@ export class RegisterPageComponent implements OnInit {
validation() {
this.firstName = this.firstName.trim();
this.lastName = this.lastName.trim();
- this.nickName = this.nickName.trim();
+ this.username = this.username.trim();
this.email = this.email.trim();
this.firstNameValidation();
this.lastNameValidation();
- //this.nickNameValidation();
+ this.usernameValidation();
this.emailValidation();
this.passwordValidation();
- if (!(this.wrongFirstNameBool || this.wrongLastNameBool || this.wrongNickNameBool ||
+ if (!(this.wrongFirstNameBool || this.wrongLastNameBool || this.wrongUsernameBool ||
this.wrongEmailBool || this.wrongPass1Bool || this.wrongPass2Bool)) { //sve ok, registruj ga
let user = {
firstName: this.firstName,
lastName: this.lastName,
- username: this.nickName,
+ username: this.username,
password: this.pass1,
email: this.email
}
@@ -123,18 +136,22 @@ export class RegisterPageComponent implements OnInit {
.subscribe(
(response) => {
console.log(response);
- if (response === 'User added')
- this.router.navigate(['/login']); //registracija uspesna, idi na login
- else if (response === 'Email Already Exists')
+ if (response === 'User added') {
+ this.resetData();
+ (<HTMLSelectElement>document.getElementById('linkToLoginModal')).click();
+ }
+ else if (response === 'Email Already Exists') {
alert('Nalog sa unetim email-om već postoji!');
- else if (response === 'Username Already Exists')
- alert('Nalog sa unetim korisnićkim imenom već postoji!');
+ (<HTMLSelectElement>document.getElementById('email')).focus();
+ }
+ else if (response === 'Username Already Exists') {
+ alert('Nalog sa unetim korisničkim imenom već postoji!');
+ (<HTMLSelectElement>document.getElementById('username-register')).focus();
+ }
}
);
}
}
-
-
}
diff --git a/frontend/src/app/_pages/add-model/add-model.component.css b/frontend/src/app/_pages/add-model/add-model.component.css
index e69de29b..4bf569cc 100644
--- a/frontend/src/app/_pages/add-model/add-model.component.css
+++ b/frontend/src/app/_pages/add-model/add-model.component.css
@@ -0,0 +1,18 @@
+#header {
+ background-color: #003459;
+ padding-top: 30px;
+ padding-bottom: 20px;
+}
+#header h1 {
+ font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
+ text-align: center;
+ color: white;
+}
+
+#container {
+ border-radius: 8px;
+}
+
+#wrapper {
+ color: #003459;
+} \ No newline at end of file
diff --git a/frontend/src/app/_pages/add-model/add-model.component.html b/frontend/src/app/_pages/add-model/add-model.component.html
index bc292bb9..004f308b 100644
--- a/frontend/src/app/_pages/add-model/add-model.component.html
+++ b/frontend/src/app/_pages/add-model/add-model.component.html
@@ -1,189 +1,257 @@
-<div class="container p-3" style="background-color: rgb(249, 251, 253); min-height: 100%;">
+<div id="header">
+ <h1>Napravite svoj model veštačke neuronske mreže</h1>
+</div>
- <h2 class="my-4 text-primary"> Nov model: </h2>
- <div class="form-group row align-items-center">
- <label for="name" class="col-sm-2 col-form-label col-form-label-lg">Naziv</label>
- <div class="col-sm-7">
- <input type="text" class="form-control form-control-lg" name="name" placeholder="Naziv..."
- [(ngModel)]="newModel.name">
+<div id="wrapper">
+
+ <div id="container" class="container p-5" style="background-color: white; min-height: 100%;">
+
+ <div class="form-group row mb-4 d-flex justify-content-center"> <!--justify-content-center-->
+ <h2 class="col-2"> Nov model: </h2>
+ <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 class="col-2">
+ <label for="dateCreated" class="col-form-label">Datum:</label> &nbsp;&nbsp;
+ <input type="text" class="form-control-plaintext" id="dateCreated" placeholder="--/--/--"
+ value="{{newModel.dateCreated | date: 'dd/MM/yyyy'}}" readonly>
+ </div>
</div>
-
- <div class="col-sm-3">
- <input type="text" class="form-control-plaintext text-center" id="dateCreated" placeholder="--/--/--"
- value="{{newModel.dateCreated | date: 'dd/MM/yyyy'}}" readonly>
+
+ <div class="mt-5 justify-content-center">
+ <h2>Izvor podataka:</h2>
+ <app-dataset-load id="dataset" (loaded)="datasetLoaded = true"></app-dataset-load>
</div>
- </div>
- <div class="form-group row my-2">
- <label for="desc" class="col-sm-2 col-form-label">Opis</label>
- <div class="col-sm-10">
- <textarea class="form-control" name="desc" rows="3" [(ngModel)]="newModel.description"></textarea>
+ <div *ngIf="datasetLoaded">
+ <div *ngIf="datasetLoadComponent" class="row">
+ <div class="col d-flex justify-content-center">
+ <h3>Izaberite ulazne kolone:</h3>
+ <div id="divInputs" class="form-check mt-2">
+ <br>
+ <div *ngFor="let item of datasetLoadComponent.dataset.header; let i = index">
+ <input *ngIf="i == 0" class="form-check-input" type="checkbox" value="{{item}}" id="cb_{{item}}" name="cbs" checked>
+ <input *ngIf="i != 0" class="form-check-input" type="checkbox" value="{{item}}" id="cb_{{item}}" name="cbs">&nbsp;
+ <label class="form-check-label" for="cb_{{item}}">
+ {{item}}
+ </label>
+ </div>
+ </div>
+ </div>
+ <div class="col d-flex justify-content-left">
+ <h3>Izaberite izlaznu kolonu:</h3>
+ <div id="divOutputs" class="form-check mt-2">
+ <br>
+ <div *ngFor="let item of datasetLoadComponent.dataset.header; let i = index">
+ <input *ngIf="i == 0" class="form-check-input" type="radio" value="{{item}}" id="rb_{{item}}" name="rbs" checked>
+ <input *ngIf="i != 0" class="form-check-input" type="radio" value="{{item}}" id="rb_{{item}}" name="rbs">&nbsp;
+ <label class="form-check-label" for="rb_{{item}}">
+ {{item}}
+ </label>
+ </div>
+ </div>
+ </div>
+ </div>
</div>
- </div>
- <!--<div class="form-group row">
- <label for="value" class="col-4">Vrednost</label>
- <div class="input-group">
- <input type="number" min="0" class="form-control" name="value" placeholder="Vrednost..."
- [(ngModel)]="newModel.value">
- <div class="input-group-prepend">
- <span class="input-group-text">#</span>
- </div>
- <input type="number" min="1" class="form-control" name="count" placeholder="Br." [(ngModel)]="newModel.count">
- <input type="text" class="form-control" name="sum" placeholder="Suma"
- value="=({{newModel.value * newModel.count}})" readonly>
- </div>
- </div>-->
+
+
+ <h2 class="mt-5 mb-4">Parametri treniranja:</h2>
- <div class="my-4">
- <label for="dataset">Izvor podataka:</label>
- <app-dataset-load id="dataset"></app-dataset-load>
- </div>
-
- <div class="form-group row my-2">
- <div class="col-sm-2 col-form-label">
- <label for="type" class="form-check-label">Podela test skupa:
- <input class="mx-3 form-check-input" type="checkbox" [checked]="newModel.randomTestSet"
- (change)="newModel.randomTestSet = !newModel.randomTestSet">
- </label>
-
- </div>
<div>
- <input type="range" min="0.1" max="0.9" step="0.1" class="form-control" name="randomTestSetDistribution"
- [disabled]="!newModel.randomTestSet" [(ngModel)]="newModel.randomTestSetDistribution">
- </div>
- </div>
-
- <h3> Parametri treniranja </h3>
-
- <div class="form-group row my-2">
- <label for="type" class="col-sm-2 col-form-label">Tip mreže: </label>
- <div class="col-sm-10">
- <select id=typeOptions class="form-control" name="type" [(ngModel)]="newModel.type">
- <option *ngFor="let option of Object.keys(ANNType); let optionName of Object.values(ANNType)"
- [value]="option">
- {{ optionName }}
- </option>
- </select>
- </div>
- </div>
-
- <div class="form-group row my-2">
- <label for="encoding" class="col-sm-2 col-form-label">Enkoding: </label>
- <div class="col-sm-10">
- <select id=encodingOptions class="form-control" name="encoding" [(ngModel)]="newModel.encoding">
- <option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)"
- [value]="option">
- {{ optionName }}
- </option>
- </select>
- </div>
- </div>
+ <div class="row p-2">
+ <div class="col-1">
+ </div>
+ <div class="col-3">
+ <label for="type" class="col-form-label">Tip mreže: </label>
+ </div>
+ <div class="col-2">
+ <select id=typeOptions class="form-control" name="type" [(ngModel)]="newModel.type">
+ <option *ngFor="let option of Object.keys(ANNType); let optionName of Object.values(ANNType)"
+ [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">
+ </div>
+ </div>
- <div class="form-group row my-2">
- <label for="optimizer" class="col-sm-2 col-form-label">Optimizacija: </label>
- <div class="col-sm-10">
- <select id=optimizerOptions class="form-control" 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>
+ <div class="row p-2">
+ <div class="col-1">
+ </div>
+ <div class="col-3">
+ <label for="encoding" class="col-form-label">Enkoding: </label>
+ </div>
+ <div class="col-2">
+ <select id=encodingOptions class="form-control" name="encoding" [(ngModel)]="newModel.encoding">
+ <option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)"
+ [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">
+ </div>
+ </div>
- <div class="form-group row my-2">
- <label for="lossFunction" class="col-sm-2 col-form-label">Funkcija obrade gubitka: </label>
- <div class="col-sm-10">
- <select id=lossFunctionOptions class="form-control" name="lossFunction" [(ngModel)]="newModel.lossFunction">
- <option *ngFor="let option of Object.keys(LossFunction); let optionName of Object.values(LossFunction)"
- [value]="option">
- {{ optionName }}
- </option>
- </select>
- </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-control" 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="batchSize" class="col-form-label">Broj uzorka po iteraciji: </label>
+ </div>
+ <div class="col-1">
+ <input type="number" min="1" class="form-control" name="batchSize" [(ngModel)]="newModel.batchSize">
+ </div>
+ </div>
- <div class="form-group row my-2">
- <label for="inputNeurons" class="col-sm-2 col-form-label">Broj ulaznih neurona: </label>
- <div class="col-sm-10">
- <input type="number" min="1" class="form-control" name="inputNeurons" [(ngModel)]="newModel.inputNeurons">
- </div>
- </div>
+ <div class="row p-2">
+ <div class="col-1">
+ </div>
+ <div class="col-3">
+ <label for="lossFunction" class="col-form-label">Funkcija obrade gubitka: </label>
+ </div>
+ <div class="col-2">
+ <select id=lossFunctionOptions class="form-control" name="lossFunction" [(ngModel)]="newModel.lossFunction">
+ <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 mt-2">
+ <label for="type" class="form-check-label">Nasumičan redosled podataka?</label>
+ <input class="mx-3 form-check-input" type="checkbox" [(ngModel)]="newModel.randomOrder" type="checkbox" value="" checked>
+ </div>
+ <div class="col-1">
+ </div>
+ </div>
- <div class="form-group row my-2">
- <label for="inputLayerActivationFunction" class="col-sm-2 col-form-label">Funkcija aktivacije ulaznog sloja:
- </label>
- <div class="col-sm-10">
- <select id=inputLayerActivationFunctionOptions class="form-control" name="inputLayerActivationFunction"
- [(ngModel)]="newModel.inputLayerActivationFunction">
- <option
- *ngFor="let option of Object.keys(ActivationFunction); let optionName of Object.values(ActivationFunction)"
- [value]="option">
- {{ optionName }}
- </option>
- </select>
- </div>
- </div>
+ <div class="row p-2">
+ <div class="col-1">
+ </div>
+ <div class="col-3">
+ <label for="inputLayerActivationFunction" class="col-form-label">Funkcija aktivacije ulaznog sloja:</label>
+ </div>
+ <div class="col-2">
+ <select id=inputLayerActivationFunctionOptions class="form-control" name="inputLayerActivationFunction"
+ [(ngModel)]="newModel.inputLayerActivationFunction">
+ <option
+ *ngFor="let option of Object.keys(ActivationFunction); let optionName of Object.values(ActivationFunction)"
+ [value]="option">
+ {{ optionName }}
+ </option>
+ </select>
+ </div>
+ <div class="col-1">
+ </div>
+ <div class="col-5">
+ <label for="type" class="form-check-label">Podela test skupa:&nbsp;&nbsp;
+ <input class="form-check-input" type="checkbox" [checked]="newModel.randomTestSet"
+ (change)="newModel.randomTestSet = !newModel.randomTestSet">
+ </label> &nbsp;&nbsp;&nbsp;&nbsp;
+ test
+ <mat-slider min="0.1" max="0.9" step="0.1" value="0.2" name="randomTestSetDistribution" thumbLabel
+ [disabled]="!newModel.randomTestSet" [(ngModel)]="newModel.randomTestSetDistribution">
+ </mat-slider>
+ trening
+ </div>
+ <div class="col">
+ </div>
+ </div>
- <div class="form-group row my-2">
- <label for="hiddenLayerNeurons" class="col-sm-2 col-form-label">Broj neurona skrivenih slojeva: </label>
- <div class="col-sm-10">
- <input type="number" min="1" class="form-control" name="hiddenLayerNeurons"
- [(ngModel)]="newModel.hiddenLayerNeurons">
- </div>
- </div>
+ <div class="row p-2">
+ <div class="col-1">
+ </div>
+ <div class="col-3">
+ <label for="hiddenLayerActivationFunction" class="col-form-label">Funkcija aktivacije skrivenih slojeva:</label>
+ </div>
+ <div class="col-2">
+ <select id=hiddenLayerActivationFunctionOptions class="form-control" name="hiddenLayerActivationFunction"
+ [(ngModel)]="newModel.hiddenLayerActivationFunction">
+ <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 class="col">
+ </div>
+ </div>
- <div class="form-group row my-2">
- <label for="hiddenLayerActivationFunction" class="col-sm-2 col-form-label">Funkcija aktivacije skrivenih
- slojeva:
- </label>
- <div class="col-sm-10">
- <select id=hiddenLayerActivationFunctionOptions class="form-control" name="hiddenLayerActivationFunction"
- [(ngModel)]="newModel.hiddenLayerActivationFunction">
- <option
- *ngFor="let option of Object.keys(ActivationFunction); let optionName of Object.values(ActivationFunction)"
- [value]="option">
- {{ optionName }}
- </option>
- </select>
+ <div class="row p-2">
+ <div class="col-1">
+ </div>
+ <div class="col-3">
+ <label for="outputLayerActivationFunction" class="col-form-label">Funkcija aktivacije izlaznog sloja:</label>
+ </div>
+ <div class="col-2">
+ <select id=outputLayerActivationFunctionOptions class="form-control" 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 class="col">
+ </div>
+ </div>
</div>
- </div>
- <div class="form-group row my-2">
- <label for="hiddenLayers" class="col-sm-2 col-form-label">Broj skrivenih slojeva: </label>
- <div class="col-sm-10">
- <input type="number" min="1" class="form-control" name="hiddenLayers" [(ngModel)]="newModel.hiddenLayers">
- </div>
- </div>
- <div class="form-group row my-2">
- <label for="outputLayerActivationFunction" class="col-sm-2 col-form-label">Funkcija aktivacije izlaznog
- sloja:
- </label>
- <div class="col-sm-10">
- <select id=outputLayerActivationFunctionOptions class="form-control" name="outputLayerActivationFunction"
- [(ngModel)]="newModel.outputLayerActivationFunction">
- <option
- *ngFor="let option of Object.keys(ActivationFunction); let optionName of Object.values(ActivationFunction)"
- [value]="option">
- {{ optionName }}
- </option>
- </select>
+ <br><br>
+ <div class="form-group row mt-5 mb-3">
+ <div class="col"></div>
+ <button class="btn btn-lg col-4" style="background-color:#003459; color:white;" (click)="addModel();">Sačuvaj model</button>
+ <div class="col"></div>
+ <button class="btn btn-lg col-4" style="background-color:#003459; color:white;" (click)="trainModel();">Treniraj model</button>
+ <div class="col"></div>
</div>
- </div>
- <div class="form-group row my-2">
- <label for="batchSize" class="col-sm-2 col-form-label">Broj uzorka po iteraciji: </label>
- <div class="col-sm-10">
- <input type="number" min="1" class="form-control" name="batchSize" [(ngModel)]="newModel.batchSize">
- </div>
</div>
+</div>
- <div class=" form-group row my-4">
- <div class="col-4"></div>
- <button class="btn btn-lg btn-primary col-4" (click)="addModel();">Dodaj</button>
- <div class="col-4"></div>
- </div>
-</div> \ No newline at end of file
diff --git a/frontend/src/app/_pages/add-model/add-model.component.ts b/frontend/src/app/_pages/add-model/add-model.component.ts
index 3cb47d61..01e8ade9 100644
--- a/frontend/src/app/_pages/add-model/add-model.component.ts
+++ b/frontend/src/app/_pages/add-model/add-model.component.ts
@@ -1,6 +1,10 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { Observable, of } from 'rxjs';
import Model from 'src/app/_data/Model';
import { ANNType, Encoding, ActivationFunction, LossFunction, Optimizer } from 'src/app/_data/Model';
+import { DatasetLoadComponent } from 'src/app/_elements/dataset-load/dataset-load.component';
+import { ModelsService } from 'src/app/_services/models.service';
+
@Component({
selector: 'app-add-model',
@@ -9,7 +13,10 @@ import { ANNType, Encoding, ActivationFunction, LossFunction, Optimizer } from '
})
export class AddModelComponent implements OnInit {
- newModel: Model
+ @ViewChild(DatasetLoadComponent) datasetLoadComponent?: DatasetLoadComponent;
+ datasetLoaded: boolean = false;
+
+ newModel: Model;
ANNType = ANNType;
Encoding = Encoding;
@@ -18,7 +25,7 @@ export class AddModelComponent implements OnInit {
Optimizer = Optimizer;
Object = Object;
- constructor() {
+ constructor(private models: ModelsService) {
this.newModel = new Model();
}
@@ -26,7 +33,64 @@ export class AddModelComponent implements OnInit {
}
addModel() {
- //TODO
+ this.saveModel(false); //trajno cuvanje
+ }
+ trainModel() {
+ this.saveModel(true).subscribe((modelId : any) => {
+ if (modelId)
+ this.models.trainModel(modelId);
+ }); //privremeno cuvanje modela => vraca id sacuvanog modela koji cemo da treniramo sad
+ }
+ saveModel(temporary: boolean) : any {
+ if (this.datasetLoadComponent)
+ this.models.addDataset(this.datasetLoadComponent?.dataset).subscribe((response) => {//id dataseta je response
+ this.newModel.datasetId = response;
+
+ this.getCheckedInputCols();
+ this.getCheckedOutputCol();
+ if (this.validationInputsOutput())
+ return this.models.addModel(this.newModel); //id modela
+ return of(null);
+ });
+ }
+
+ getCheckedInputCols() {
+ this.newModel.inputColumns = [];
+ let checkboxes = document.getElementsByName("cbs");
+
+ for (let i = 0; i < checkboxes.length; i++) {
+ let thatCb = <HTMLInputElement>checkboxes[i];
+ if (thatCb.checked)
+ this.newModel.inputColumns.push(thatCb.value);
+ }
+ //console.log(this.checkedInputCols);
+ }
+ getCheckedOutputCol() {
+ this.newModel.columnToPredict = '';
+ let radiobuttons = document.getElementsByName("rbs");
+
+ for (let i = 0; i < radiobuttons.length; i++) {
+ let thatRb = <HTMLInputElement>radiobuttons[i];
+ if (thatRb.checked) {
+ this.newModel.columnToPredict = thatRb.value;
+ break;
+ }
+ }
+ //console.log(this.checkedOutputCol);
+ }
+ validationInputsOutput() : boolean {
+ if (this.newModel.inputColumns.length == 0) {
+ alert("Molimo Vas da izaberete ulaznu kolonu/kolone za mrežu.")
+ return false;
+ }
+ for (let i = 0; i < this.newModel.inputColumns.length; i++) {
+ if (this.newModel.inputColumns[i] == this.newModel.columnToPredict) {
+ let colName = this.newModel.columnToPredict;
+ alert("Izabrali ste istu kolonu (" + colName + ") kao ulaznu i izlaznu iz mreže. Korigujte izbor.");
+ return false;
+ }
+ }
+ return true;
}
}
diff --git a/frontend/src/app/_pages/browse-datasets/browse-datasets.component.css b/frontend/src/app/_pages/browse-datasets/browse-datasets.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/browse-datasets/browse-datasets.component.css
diff --git a/frontend/src/app/_pages/browse-datasets/browse-datasets.component.html b/frontend/src/app/_pages/browse-datasets/browse-datasets.component.html
new file mode 100644
index 00000000..fa38a1bc
--- /dev/null
+++ b/frontend/src/app/_pages/browse-datasets/browse-datasets.component.html
@@ -0,0 +1 @@
+<p>browse-datasets works!</p>
diff --git a/frontend/src/app/_pages/only-authorized/only-authorized.component.spec.ts b/frontend/src/app/_pages/browse-datasets/browse-datasets.component.spec.ts
index 82a01f63..fda74dbe 100644
--- a/frontend/src/app/_pages/only-authorized/only-authorized.component.spec.ts
+++ b/frontend/src/app/_pages/browse-datasets/browse-datasets.component.spec.ts
@@ -1,20 +1,20 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { OnlyAuthorizedComponent } from './only-authorized.component';
+import { BrowseDatasetsComponent } from './browse-datasets.component';
-describe('OnlyAuthorizedComponent', () => {
- let component: OnlyAuthorizedComponent;
- let fixture: ComponentFixture<OnlyAuthorizedComponent>;
+describe('BrowseDatasetsComponent', () => {
+ let component: BrowseDatasetsComponent;
+ let fixture: ComponentFixture<BrowseDatasetsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [ OnlyAuthorizedComponent ]
+ declarations: [ BrowseDatasetsComponent ]
})
.compileComponents();
});
beforeEach(() => {
- fixture = TestBed.createComponent(OnlyAuthorizedComponent);
+ fixture = TestBed.createComponent(BrowseDatasetsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
diff --git a/frontend/src/app/_pages/browse-datasets/browse-datasets.component.ts b/frontend/src/app/_pages/browse-datasets/browse-datasets.component.ts
new file mode 100644
index 00000000..dba6c25e
--- /dev/null
+++ b/frontend/src/app/_pages/browse-datasets/browse-datasets.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-browse-datasets',
+ templateUrl: './browse-datasets.component.html',
+ styleUrls: ['./browse-datasets.component.css']
+})
+export class BrowseDatasetsComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/frontend/src/app/_pages/browse-predictors/browse-predictors.component.css b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.css
diff --git a/frontend/src/app/_pages/browse-predictors/browse-predictors.component.html b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.html
new file mode 100644
index 00000000..01c4af82
--- /dev/null
+++ b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.html
@@ -0,0 +1 @@
+<p>browse-predictors works!</p>
diff --git a/frontend/src/app/_pages/browse-predictors/browse-predictors.component.spec.ts b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.spec.ts
new file mode 100644
index 00000000..6d13fedf
--- /dev/null
+++ b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BrowsePredictorsComponent } from './browse-predictors.component';
+
+describe('BrowsePredictorsComponent', () => {
+ let component: BrowsePredictorsComponent;
+ let fixture: ComponentFixture<BrowsePredictorsComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ BrowsePredictorsComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(BrowsePredictorsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_pages/browse-predictors/browse-predictors.component.ts b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.ts
new file mode 100644
index 00000000..b4fb2a9d
--- /dev/null
+++ b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-browse-predictors',
+ templateUrl: './browse-predictors.component.html',
+ styleUrls: ['./browse-predictors.component.css']
+})
+export class BrowsePredictorsComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/frontend/src/app/_pages/home/home.component.css b/frontend/src/app/_pages/home/home.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/home/home.component.css
diff --git a/frontend/src/app/_pages/home/home.component.html b/frontend/src/app/_pages/home/home.component.html
new file mode 100644
index 00000000..7245f602
--- /dev/null
+++ b/frontend/src/app/_pages/home/home.component.html
@@ -0,0 +1,53 @@
+<div class="d-flex flex-column align-items-center bg-light">
+ <img src="../../../assets/svg/logo.svg" class="bi me-2" width="256" height="256" role="img">
+ <div *ngIf="shared.loggedIn" class="d-flex flex-column align-items-center">
+ <h2 class="my-4">Započnite sa treniranjem!</h2>
+ <div id="cards" class="row align-items-center justify-content-center">
+ <div class="card shadow col-3 m-1" style="width: 18rem;">
+ <div class="card-body">
+ <mat-icon width="48px" height="48px"
+ style="font-size: 48px; margin-left: 50%; transform: translateX(-100%);">storage</mat-icon>
+ <h3 class="card-title my-2">Moji izvori podataka</h3>
+ <p class="card-text">
+ <a class="stretched-link" routerLink="my-datasets">Preuredite</a> vaše izvore
+ podataka, ili
+ dodajte novi.
+ </p>
+ </div>
+ </div>
+ <div class="card shadow col-3 m-1" style="width: 18rem;">
+ <div class="card-body">
+ <mat-icon width="48px" height="48px"
+ style="font-size: 48px; margin-left: 50%; transform: translateX(-100%);">model_training
+ </mat-icon>
+ <h3 class="card-title my-2">Moji modeli</h3>
+ <p class="card-text">
+ <a class="stretched-link" routerLink="my-models">Pregledajte</a> vaše modele, menjajte ih,
+ napravite nove modele, ili
+ ih obrišite.
+ </p>
+ </div>
+ </div>
+ <div class="card shadow col-3 m-1" style="width: 18rem;">
+ <div class="card-body">
+ <mat-icon width="48px" height="48px"
+ style="font-size: 48px; margin-left: 50%; transform: translateX(-100%);">batch_prediction
+ </mat-icon>
+ <h3 class="card-title my-2">Rezultati treniranja</h3>
+ <p class="card-text">
+ <a class="stretched-link" routerLink="my-predictors">Pregledajte</a> sve vaše trenirane
+ modele,
+ koristite ih da predvidite vrednosti za red ili skup podataka, ili ih obrišite.
+ </p>
+ </div>
+ </div>
+ </div>
+
+ </div>
+ <h2 class="my-4">Pogledajte javne izvore podataka!</h2>
+ <app-carousel [items]="publicDatasets">
+ </app-carousel>
+ <h2 class="my-4">Iskoristite već trenirane modele!</h2>
+ <app-carousel [items]="publicPredictors">
+ </app-carousel>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_pages/home/home.component.spec.ts b/frontend/src/app/_pages/home/home.component.spec.ts
new file mode 100644
index 00000000..2c5a1726
--- /dev/null
+++ b/frontend/src/app/_pages/home/home.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { HomeComponent } from './home.component';
+
+describe('HomeComponent', () => {
+ let component: HomeComponent;
+ let fixture: ComponentFixture<HomeComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ HomeComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(HomeComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_pages/home/home.component.ts b/frontend/src/app/_pages/home/home.component.ts
new file mode 100644
index 00000000..7e4471e8
--- /dev/null
+++ b/frontend/src/app/_pages/home/home.component.ts
@@ -0,0 +1,45 @@
+import { Component, OnInit } from '@angular/core';
+import Dataset from 'src/app/_data/Dataset';
+import Predictor from 'src/app/_data/Predictor';
+import { ItemDatasetComponent } from 'src/app/_elements/item-dataset/item-dataset.component';
+import shared from 'src/app/Shared';
+
+@Component({
+ selector: 'app-home',
+ templateUrl: './home.component.html',
+ styleUrls: ['./home.component.css']
+})
+export class HomeComponent implements OnInit {
+
+ publicDatasets: Dataset[];
+ publicPredictors: Predictor[];
+
+ shared = shared;
+
+ constructor() {
+ this.publicDatasets = [
+ new Dataset('Titanik', 'Titanik', ['Kolona1', 'Kolona2', 'Ime', 'OsobaJePreživela']),
+ new Dataset('Drugi Dataset', 'Lorem ipsum dolor sir amet', ['jabuka', 'kruska', 'jagoda']),
+ new Dataset('Dataset III', 'Kratak opis izvora podataka', ['c1', 'c2', 'c3', 'c4', 'c5']),
+ new Dataset('Drugi Dataset', 'Lorem ipsum dolor sir amet', ['jabuka', 'kruska', 'jagoda']),
+ new Dataset('Dataset III', 'Kratak opis izvora podataka', ['c1', 'c2', 'c3', 'c4', 'c5']),
+ new Dataset('Drugi Dataset', 'Lorem ipsum dolor sir amet', ['jabuka', 'kruska', 'jagoda']),
+ new Dataset('Dataset III', 'Kratak opis izvora podataka', ['c1', 'c2', 'c3', 'c4', 'c5']),
+ new Dataset('Dataset III', 'Kratak opis izvora podataka', ['c1', 'c2', 'c3', 'c4', 'c5'])
+ ]
+ this.publicPredictors = [
+ new Predictor('Preživeli', 'Za uneto ime osobe, predvidja da li je ta osoba preživela ili ne.', ['Ime'], 'OsobaJePreživela'),
+ new Predictor('Drugi model', 'Lorem ipsum dolor sir amet', ['kruska'], 'jagoda'),
+ new Predictor('Treći model', 'Kratak opis modela', ['c1', 'c2', 'c3'], 'c5'),
+ new Predictor('Drugi model', 'Lorem ipsum dolor sir amet', ['kruska'], 'jagoda'),
+ new Predictor('Treći model', 'Kratak opis modela', ['c1', 'c2', 'c3'], 'c5'),
+ new Predictor('Drugi model', 'Lorem ipsum dolor sir amet', ['kruska'], 'jagoda'),
+ new Predictor('Treći model', 'Kratak opis modela', ['c1', 'c2', 'c3'], 'c5'),
+ new Predictor('Treći model', 'Kratak opis modela', ['c1', 'c2', 'c3'], 'c5')
+ ]
+ }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/frontend/src/app/_pages/login-page/login-page.component.html b/frontend/src/app/_pages/login-page/login-page.component.html
deleted file mode 100644
index 8deb5290..00000000
--- a/frontend/src/app/_pages/login-page/login-page.component.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!--<script>
- $(document).ready(function(){
- $(".btn").click(function(){
- $("#exampleModal").modal('show');
- });
-
- $('#exampleModal').modal({
-     backdrop: 'static',
-     keyboard: false
- });
- });
-</script>-->
-
-<!-- Button trigger modal -->
-<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalForLogin" (click)="openModal()">
- Open Modal
- </button>
-
-<!--
-<div style="min-height: 100vh; position: relative;">
-
- <div class="container p-5 rounded-3 shadow-sm border" style="max-width: 50em; margin-top: 50px;">
- <h3 class="text-center pb-5">Prijavite se</h3>
- <form>
- <div class="form-outline mb-4">
- <label class="form-label" for="username">Korisničko ime</label>
- <input [(ngModel)]="username" name="username" type="text" id="username"
- class="form-control form-control-lg" placeholder="Unesite korisničko ime..." />
- </div>
-
- <div class="form-outline mb-3">
- <label class="form-label" for="password">Lozinka</label>
- <input [(ngModel)]="password" name="password" type="password" id="password"
- class="form-control form-control-lg" placeholder="Unesite lozinku..." />
- </div>
-
- <div class="text-center text-lg-start mt-4 pt-2">
- <p *ngIf="wrongCreds" class="small fw-bold mt-2 pt-1 mb-0 text-danger">Lozinka ili e-mail su pogrešni
- </p>
- <br>
-
- <button type="button" class="btn btn-primary btn-lg"
- style="padding-left: 2.5rem; padding-right: 2.5rem;" (click)="onSubmit()">Prijava
- </button>
-
- <br>
- <p class="small fw-bold mt-2 pt-1 mb-0">Još uvek nemate nalog?
- <a routerLink="/register" class="link-danger">Registrujte se</a>
- </p>
- </div>
- </form>
- </div>
-
-</div>
---> \ No newline at end of file
diff --git a/frontend/src/app/_pages/login-page/login-page.component.ts b/frontend/src/app/_pages/login-page/login-page.component.ts
deleted file mode 100644
index e5366283..00000000
--- a/frontend/src/app/_pages/login-page/login-page.component.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
-import { CookieService } from 'ngx-cookie-service';
-import { AuthService } from 'src/app/_services/auth.service';
-
-import { LoginModalComponent } from 'src/app/_modals/login-modal/login-modal.component';
-import { MDBModalRef, MDBModalService } from 'ng-uikit-pro-standard';
-
-
-declare var window: any;
-
-@Component({
- selector: 'app-login-page',
- templateUrl: './login-page.component.html',
- styleUrls: ['./login-page.component.css'],
-
-})
-export class LoginPageComponent{
-
- modalRef?: MDBModalRef;
-
- //email: string = '';
- username: string = '';
- password: string = '';
-
- public wrongCreds: boolean = false; //RAZMOTRITI
- //public notApproved: boolean = false; //RAZMOTRITI
-
- formModal: any;
-
- constructor(
- private authService: AuthService,
- private cookie: CookieService,
- private router: Router,
- private modalService: MDBModalService
- ) { }
-
- openModal() {
- //this.modalRef = this.modalService.show(LoginModalComponent);
- }
- /*
- ngOnInit(): void {
- this.formModal = new window.bootstrap.Modal(
- document.getElementById("exampleModal")
- );
- }
-
- openModal() {
- this.formModal.show();
- //console.log("ok");
- //(<HTMLInputElement>document.getElementById("exampleModal")).style.display = "block";
- }
-
- onSubmit() {
-
- this.authService.login(this.username, this.password).subscribe((response) => {
- console.log(response);
- this.cookie.set('token', response);
- this.router.navigate(['add-model']);
- });
- }
-*/
-}
diff --git a/frontend/src/app/_pages/my-datasets/my-datasets.component.css b/frontend/src/app/_pages/my-datasets/my-datasets.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/my-datasets/my-datasets.component.css
diff --git a/frontend/src/app/_pages/my-datasets/my-datasets.component.html b/frontend/src/app/_pages/my-datasets/my-datasets.component.html
new file mode 100644
index 00000000..4b3095be
--- /dev/null
+++ b/frontend/src/app/_pages/my-datasets/my-datasets.component.html
@@ -0,0 +1 @@
+<p>my-datasets works!</p>
diff --git a/frontend/src/app/_pages/my-datasets/my-datasets.component.spec.ts b/frontend/src/app/_pages/my-datasets/my-datasets.component.spec.ts
new file mode 100644
index 00000000..fc1fc3f3
--- /dev/null
+++ b/frontend/src/app/_pages/my-datasets/my-datasets.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MyDatasetsComponent } from './my-datasets.component';
+
+describe('MyDatasetsComponent', () => {
+ let component: MyDatasetsComponent;
+ let fixture: ComponentFixture<MyDatasetsComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ MyDatasetsComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MyDatasetsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_pages/my-datasets/my-datasets.component.ts b/frontend/src/app/_pages/my-datasets/my-datasets.component.ts
new file mode 100644
index 00000000..af5eab97
--- /dev/null
+++ b/frontend/src/app/_pages/my-datasets/my-datasets.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-my-datasets',
+ templateUrl: './my-datasets.component.html',
+ styleUrls: ['./my-datasets.component.css']
+})
+export class MyDatasetsComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/frontend/src/app/_pages/my-models/my-models.component.css b/frontend/src/app/_pages/my-models/my-models.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/my-models/my-models.component.css
diff --git a/frontend/src/app/_pages/my-models/my-models.component.html b/frontend/src/app/_pages/my-models/my-models.component.html
new file mode 100644
index 00000000..2fea257d
--- /dev/null
+++ b/frontend/src/app/_pages/my-models/my-models.component.html
@@ -0,0 +1 @@
+<p>my-models works!</p>
diff --git a/frontend/src/app/_pages/my-models/my-models.component.spec.ts b/frontend/src/app/_pages/my-models/my-models.component.spec.ts
new file mode 100644
index 00000000..e431d04c
--- /dev/null
+++ b/frontend/src/app/_pages/my-models/my-models.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MyModelsComponent } from './my-models.component';
+
+describe('MyModelsComponent', () => {
+ let component: MyModelsComponent;
+ let fixture: ComponentFixture<MyModelsComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ MyModelsComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MyModelsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_pages/my-models/my-models.component.ts b/frontend/src/app/_pages/my-models/my-models.component.ts
new file mode 100644
index 00000000..e9bc52de
--- /dev/null
+++ b/frontend/src/app/_pages/my-models/my-models.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-my-models',
+ templateUrl: './my-models.component.html',
+ styleUrls: ['./my-models.component.css']
+})
+export class MyModelsComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/frontend/src/app/_pages/my-predictors/my-predictors.component.css b/frontend/src/app/_pages/my-predictors/my-predictors.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/my-predictors/my-predictors.component.css
diff --git a/frontend/src/app/_pages/my-predictors/my-predictors.component.html b/frontend/src/app/_pages/my-predictors/my-predictors.component.html
new file mode 100644
index 00000000..32d085af
--- /dev/null
+++ b/frontend/src/app/_pages/my-predictors/my-predictors.component.html
@@ -0,0 +1 @@
+<p>my-predictors works!</p>
diff --git a/frontend/src/app/_pages/register-page/register-page.component.spec.ts b/frontend/src/app/_pages/my-predictors/my-predictors.component.spec.ts
index 347fe9f4..37dddf6d 100644
--- a/frontend/src/app/_pages/register-page/register-page.component.spec.ts
+++ b/frontend/src/app/_pages/my-predictors/my-predictors.component.spec.ts
@@ -1,20 +1,20 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { RegisterPageComponent } from './register-page.component';
+import { MyPredictorsComponent } from './my-predictors.component';
-describe('RegisterPageComponent', () => {
- let component: RegisterPageComponent;
- let fixture: ComponentFixture<RegisterPageComponent>;
+describe('MyPredictorsComponent', () => {
+ let component: MyPredictorsComponent;
+ let fixture: ComponentFixture<MyPredictorsComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [ RegisterPageComponent ]
+ declarations: [ MyPredictorsComponent ]
})
.compileComponents();
});
beforeEach(() => {
- fixture = TestBed.createComponent(RegisterPageComponent);
+ fixture = TestBed.createComponent(MyPredictorsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
diff --git a/frontend/src/app/_pages/my-predictors/my-predictors.component.ts b/frontend/src/app/_pages/my-predictors/my-predictors.component.ts
new file mode 100644
index 00000000..b0d6e9dd
--- /dev/null
+++ b/frontend/src/app/_pages/my-predictors/my-predictors.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-my-predictors',
+ templateUrl: './my-predictors.component.html',
+ styleUrls: ['./my-predictors.component.css']
+})
+export class MyPredictorsComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/frontend/src/app/_pages/only-authorized/only-authorized.component.html b/frontend/src/app/_pages/only-authorized/only-authorized.component.html
deleted file mode 100644
index 27bbcf09..00000000
--- a/frontend/src/app/_pages/only-authorized/only-authorized.component.html
+++ /dev/null
@@ -1 +0,0 @@
-<p>only-authorized works!</p>
diff --git a/frontend/src/app/_pages/only-authorized/only-authorized.component.ts b/frontend/src/app/_pages/only-authorized/only-authorized.component.ts
deleted file mode 100644
index be88365f..00000000
--- a/frontend/src/app/_pages/only-authorized/only-authorized.component.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-
-@Component({
- selector: 'app-only-authorized',
- templateUrl: './only-authorized.component.html',
- styleUrls: ['./only-authorized.component.css']
-})
-export class OnlyAuthorizedComponent implements OnInit {
-
- constructor() { }
-
- ngOnInit(): void {
- }
-
-}
diff --git a/frontend/src/app/_pages/predict/predict.component.css b/frontend/src/app/_pages/predict/predict.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/predict/predict.component.css
diff --git a/frontend/src/app/_pages/predict/predict.component.html b/frontend/src/app/_pages/predict/predict.component.html
new file mode 100644
index 00000000..74a83b71
--- /dev/null
+++ b/frontend/src/app/_pages/predict/predict.component.html
@@ -0,0 +1 @@
+<p>predict works!</p>
diff --git a/frontend/src/app/_pages/predict/predict.component.spec.ts b/frontend/src/app/_pages/predict/predict.component.spec.ts
new file mode 100644
index 00000000..65871ecc
--- /dev/null
+++ b/frontend/src/app/_pages/predict/predict.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PredictComponent } from './predict.component';
+
+describe('PredictComponent', () => {
+ let component: PredictComponent;
+ let fixture: ComponentFixture<PredictComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ PredictComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PredictComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_pages/predict/predict.component.ts b/frontend/src/app/_pages/predict/predict.component.ts
new file mode 100644
index 00000000..0e313c65
--- /dev/null
+++ b/frontend/src/app/_pages/predict/predict.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-predict',
+ templateUrl: './predict.component.html',
+ styleUrls: ['./predict.component.css']
+})
+export class PredictComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/frontend/src/app/_pages/profile/profile.component.css b/frontend/src/app/_pages/profile/profile.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/profile/profile.component.css
diff --git a/frontend/src/app/_pages/profile/profile.component.html b/frontend/src/app/_pages/profile/profile.component.html
new file mode 100644
index 00000000..9df0576d
--- /dev/null
+++ b/frontend/src/app/_pages/profile/profile.component.html
@@ -0,0 +1 @@
+<p>profile works!</p>
diff --git a/frontend/src/app/_pages/profile/profile.component.spec.ts b/frontend/src/app/_pages/profile/profile.component.spec.ts
new file mode 100644
index 00000000..e88012e7
--- /dev/null
+++ b/frontend/src/app/_pages/profile/profile.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ProfileComponent } from './profile.component';
+
+describe('ProfileComponent', () => {
+ let component: ProfileComponent;
+ let fixture: ComponentFixture<ProfileComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ProfileComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ProfileComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_pages/profile/profile.component.ts b/frontend/src/app/_pages/profile/profile.component.ts
new file mode 100644
index 00000000..93040f3e
--- /dev/null
+++ b/frontend/src/app/_pages/profile/profile.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-profile',
+ templateUrl: './profile.component.html',
+ styleUrls: ['./profile.component.css']
+})
+export class ProfileComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/frontend/src/app/_pages/register-page/register-page.component.html b/frontend/src/app/_pages/register-page/register-page.component.html
deleted file mode 100644
index f8ae046e..00000000
--- a/frontend/src/app/_pages/register-page/register-page.component.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<div style="min-height: 100vh; position: relative;">
-
- <!-- TODO <app-navbar [activeNav]="'register'"></app-navbar>-->
-
- <div class="container" style="margin-top: 50px;">
- <div class="text-black">
- <div class="row justify-content-center">
- <div class="col-8 bg-white border rounded-3 shadow-sm p-5">
- <p class="text-center h2 fw-bold mb-5 mx-1 mx-md-4">Registracija</p>
-
- <form class="mx-1 mx-md-4">
- <!--Ime-->
- <div class="row">
- <div class="col-6 p-2">
- <label class="form-label" for="firstName">Ime</label>
- <input type="text" id="firstName" class="form-control" [(ngModel)]="firstName" name="firstName">
- <p *ngIf="wrongFirstNameBool" class="small fw-bold text-danger">Unesite ispravno ime. (minimum 1, maksimum 30 karaktera)</p>
- </div>
- <!--Prezime-->
- <div class="col-6 p-2">
- <label class="form-label" for="lastName">Prezime</label>
- <input type="text" id="lastName" class="form-control" [(ngModel)]="lastName" name="lastName" />
- <p *ngIf="wrongLastNameBool" class="small fw-bold text-danger">Unesite ispravno prezime. (minimum 1, maksimum 30 karaktera)</p>
- </div>
- </div>
- <br>
-
- <div class="row">
- <!--Korisnicko ime-->
- <div class="col-6 p-2">
- <label class="form-label" for="nickName">Korisničko ime</label>
- <input type="text" id="nickName" class="form-control" [(ngModel)]="nickName" name="nickName" />
- <p *ngIf="wrongNickNameBool" class="small fw-bold text-danger">Unesite ispravno korisničko ime.</p>
- </div>
- <!--Email-->
- <div class="col-6 p-2">
- <label class="form-label" for="email">E-mail adresa</label>
- <input type="email" id="email" class="form-control" [(ngModel)]="email" name="email" />
- <p *ngIf="wrongEmailBool" class="small fw-bold text-danger">Unesite ispravnu e-mail adresu.</p>
- </div>
- </div>
- <br>
-
- <div class="row">
- <!-- Lozinka 1. -->
- <div class="col-6 p-2">
- <label class="form-label" for="pass1">Lozinka</label>
- <input type="password" id="pass1" class="form-control" [(ngModel)]="pass1" name="pass1" />
- <p *ngIf="wrongPass1Bool" class="small fw-bold text-danger">Lozinka se mora sastojati od najmanje 6 karaktera.</p>
- </div>
-
- <!-- Lozinka 2. -->
- <div class="col-6 p-2">
- <label class="form-label" for="pass2">Potvrdite lozinku</label>
- <input type="password" id="pass2" class="form-control" [(ngModel)]="pass2" name="pass2" />
- <p *ngIf="wrongPass2Bool" class="small fw-bold text-danger">Lozinke se ne podudaraju.</p>
- </div>
- </div>
-
- <br><br><br>
- <!--Dugme Registruj se-->
- <div class="d-flex justify-content-center mx-4 mb-3 mb-lg-4">
- <button type="button" class="btn btn-primary btn-lg" (click)="validation()">Registrujte se</button>
- </div>
-
- <div class="form-check d-flex justify-content-center mb-5">
- <label class="form-check-label" class="small fw-bold mt-2 pt-1 mb-0" for="form2Example3">
- Već imate kreiran nalog?
- <a routerLink="/login" class="link-danger">Prijavite se</a>
- </label>
- </div>
- </form>
- </div>
- </div>
- </div>
- </div>
-
- <!-- TODO <app-footer></app-footer> -->
-
-</div> \ No newline at end of file
diff --git a/frontend/src/app/_pages/settings/settings.component.css b/frontend/src/app/_pages/settings/settings.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/settings/settings.component.css
diff --git a/frontend/src/app/_pages/settings/settings.component.html b/frontend/src/app/_pages/settings/settings.component.html
new file mode 100644
index 00000000..4ab2a415
--- /dev/null
+++ b/frontend/src/app/_pages/settings/settings.component.html
@@ -0,0 +1 @@
+<p>settings works!</p>
diff --git a/frontend/src/app/_pages/settings/settings.component.spec.ts b/frontend/src/app/_pages/settings/settings.component.spec.ts
new file mode 100644
index 00000000..a3a508b0
--- /dev/null
+++ b/frontend/src/app/_pages/settings/settings.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SettingsComponent } from './settings.component';
+
+describe('SettingsComponent', () => {
+ let component: SettingsComponent;
+ let fixture: ComponentFixture<SettingsComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ SettingsComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SettingsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_pages/settings/settings.component.ts b/frontend/src/app/_pages/settings/settings.component.ts
new file mode 100644
index 00000000..19862fb0
--- /dev/null
+++ b/frontend/src/app/_pages/settings/settings.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'app-settings',
+ templateUrl: './settings.component.html',
+ styleUrls: ['./settings.component.css']
+})
+export class SettingsComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit(): void {
+ }
+
+}
diff --git a/frontend/src/app/_services/auth-guard.service.ts b/frontend/src/app/_services/auth-guard.service.ts
index b6d3678d..057996e0 100644
--- a/frontend/src/app/_services/auth-guard.service.ts
+++ b/frontend/src/app/_services/auth-guard.service.ts
@@ -15,7 +15,7 @@ export class AuthGuardService implements CanActivate {
if (this.auth.isAuthenticated()) {
return true;
}
- this.router.navigate(['login']);
+ this.router.navigate(['']);
return false;
}
}
diff --git a/frontend/src/app/_services/auth.service.ts b/frontend/src/app/_services/auth.service.ts
index c96c2dae..afc1567b 100644
--- a/frontend/src/app/_services/auth.service.ts
+++ b/frontend/src/app/_services/auth.service.ts
@@ -3,6 +3,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http';
import { JwtHelperService } from '@auth0/angular-jwt';
import { CookieService } from 'ngx-cookie-service';
import { API_SETTINGS } from 'src/config';
+import shared from '../Shared';
const jwtHelper = new JwtHelperService();
@@ -11,6 +12,8 @@ const jwtHelper = new JwtHelperService();
})
export class AuthService {
+ shared = shared;
+
constructor(private http: HttpClient, private cookie: CookieService) { }
login(username: string, password: string) {
@@ -28,4 +31,49 @@ export class AuthService {
}
return false;
}
+
+ lastToken?: string;
+ refresher: any;
+
+ enableAutoRefresh() {
+ this.lastToken = this.cookie.get('token');
+ let exp = jwtHelper.getTokenExpirationDate(this.lastToken);
+ if (!exp) {
+ exp = new Date();
+ }
+ this.refresher = setTimeout(() => {
+ console.log('refreshing token!');
+ this.http.post(`${API_SETTINGS.apiURL}/auth/renewJwt`, {}, { headers: this.authHeader(), responseType: 'text' }).subscribe((response) => {
+ this.authenticate(response);
+ });
+ }, exp.getTime() - new Date().getTime());
+ }
+
+ authenticate(token: string) {
+ let exp = jwtHelper.getTokenExpirationDate(token);
+ if (!exp) {
+ exp = new Date();
+ }
+ this.cookie.set('token', token, exp);
+ this.updateUser();
+ }
+
+ updateUser() {
+ if (this.cookie.check('token')) {
+ const token = this.cookie.get('token');
+ this.shared.loggedIn = this.isAuthenticated();
+ this.enableAutoRefresh();
+ }
+ }
+
+ logOut() {
+ this.cookie.delete('token');
+ if (this.refresher)
+ clearTimeout(this.refresher);
+ this.shared.loggedIn = false;
+ }
+
+ authHeader() {
+ return new HttpHeaders().set("Authorization", "Bearer " + this.cookie.get('token'));
+ }
}
diff --git a/frontend/src/app/_services/models.service.spec.ts b/frontend/src/app/_services/models.service.spec.ts
new file mode 100644
index 00000000..b5b25752
--- /dev/null
+++ b/frontend/src/app/_services/models.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { ModelsService } from './models.service';
+
+describe('ModelsService', () => {
+ let service: ModelsService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(ModelsService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_services/models.service.ts b/frontend/src/app/_services/models.service.ts
new file mode 100644
index 00000000..80dc1ae3
--- /dev/null
+++ b/frontend/src/app/_services/models.service.ts
@@ -0,0 +1,25 @@
+import { HttpClient } from '@angular/common/http';
+import { Injectable } from '@angular/core';
+import Model from '../_data/Model';
+import { AuthService } from './auth.service';
+import { API_SETTINGS } from 'src/config';
+import Dataset from '../_data/Dataset';
+
+
+@Injectable({
+ providedIn: 'root'
+})
+export class ModelsService {
+
+ constructor(private http: HttpClient, private authService: AuthService) { }
+
+ addModel(model: Model) {
+ return this.http.post(`${API_SETTINGS.apiURL}/model/add`, model, { headers: this.authService.authHeader(), responseType: 'text' });
+ }
+ addDataset(dataset: Dataset) {
+ return this.http.post(`${API_SETTINGS.apiURL}/dataset/add`, dataset, { headers: this.authService.authHeader(), responseType: 'text' });
+ }
+ trainModel(modelId: string) {
+ return this.http.post(`${API_SETTINGS.apiURL}/model/train`, modelId, { headers: this.authService.authHeader(), responseType: 'text' });
+ }
+}
diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts
index cd86ef5c..ee43b522 100644
--- a/frontend/src/app/app-routing.module.ts
+++ b/frontend/src/app/app-routing.module.ts
@@ -2,19 +2,28 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AuthGuardService } from './_services/auth-guard.service';
-import { LoginPageComponent } from './_pages/login-page/login-page.component';
-import { OnlyAuthorizedComponent } from './_pages/only-authorized/only-authorized.component';
-import { RegisterPageComponent } from './_pages/register-page/register-page.component';
import { AddModelComponent } from './_pages/add-model/add-model.component';
-import { LoginModalComponent } from './_modals/login-modal/login-modal.component';
+import { HomeComponent } from './_pages/home/home.component';
+import { MyDatasetsComponent } from './_pages/my-datasets/my-datasets.component';
+import { MyModelsComponent } from './_pages/my-models/my-models.component';
+import { MyPredictorsComponent } from './_pages/my-predictors/my-predictors.component';
+import { BrowsePredictorsComponent } from './_pages/browse-predictors/browse-predictors.component';
+import { BrowseDatasetsComponent } from './_pages/browse-datasets/browse-datasets.component';
+import { SettingsComponent } from './_pages/settings/settings.component';
+import { ProfileComponent } from './_pages/profile/profile.component';
+import { PredictComponent } from './_pages/predict/predict.component';
const routes: Routes = [
- { path: '', redirectTo: '/login', pathMatch: 'full' },
- { path: 'login', component: LoginPageComponent },
- { path: 'register', component: RegisterPageComponent },
- { path: 'only-authorized', component: OnlyAuthorizedComponent, canActivate: [AuthGuardService] },
+ { path: '', component: HomeComponent },
{ path: 'add-model', component: AddModelComponent },
- { path: 'login-modal-test', component: LoginModalComponent }
+ { path: 'my-datasets', component: MyDatasetsComponent, canActivate: [AuthGuardService] },
+ { path: 'my-models', component: MyModelsComponent, canActivate: [AuthGuardService] },
+ { path: 'my-predictors', component: MyPredictorsComponent, canActivate: [AuthGuardService] },
+ { path: 'settings', component: SettingsComponent, canActivate: [AuthGuardService] },
+ { path: 'profile', component: ProfileComponent, canActivate: [AuthGuardService] },
+ { path: 'browse-datasets', component: BrowseDatasetsComponent },
+ { path: 'browse-predictors', component: BrowsePredictorsComponent },
+ { path: 'predict', component: PredictComponent }
];
@NgModule({
diff --git a/frontend/src/app/app.component.html b/frontend/src/app/app.component.html
index 90c6b646..35e5adb1 100644
--- a/frontend/src/app/app.component.html
+++ b/frontend/src/app/app.component.html
@@ -1 +1,4 @@
-<router-outlet></router-outlet> \ No newline at end of file
+<app-navbar></app-navbar>
+<div class="container h-100">
+ <router-outlet></router-outlet>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index d95252ad..5aa405fb 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -3,29 +3,53 @@ import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { HttpClientModule } from '@angular/common/http';
+import { MatSliderModule } from '@angular/material/slider';
+import { MatIconModule } from '@angular/material/icon';
import { AppComponent } from './app.component';
-import { LoginPageComponent } from './_pages/login-page/login-page.component';
-import { RegisterPageComponent } from './_pages/register-page/register-page.component';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
-import { OnlyAuthorizedComponent } from './_pages/only-authorized/only-authorized.component';
import { DatasetLoadComponent } from './_elements/dataset-load/dataset-load.component';
import { AddModelComponent } from './_pages/add-model/add-model.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { LoginModalComponent } from './_modals/login-modal/login-modal.component';
+import { ReactiveFormsModule } from '@angular/forms';
+import { RegisterModalComponent } from './_modals/register-modal/register-modal.component';
import { MaterialModule } from './material.module';
-import { ReactiveFormsModule } from '@angular/forms';
+import { HomeComponent } from './_pages/home/home.component';
+import { NavbarComponent } from './_elements/navbar/navbar.component';
+import { ItemPredictorComponent } from './_elements/item-predictor/item-predictor.component';
+import { ItemDatasetComponent } from './_elements/item-dataset/item-dataset.component';
+import { CarouselComponent } from './_elements/carousel/carousel.component';
+import { SettingsComponent } from './_pages/settings/settings.component';
+import { ProfileComponent } from './_pages/profile/profile.component';
+import { MyPredictorsComponent } from './_pages/my-predictors/my-predictors.component';
+import { MyDatasetsComponent } from './_pages/my-datasets/my-datasets.component';
+import { MyModelsComponent } from './_pages/my-models/my-models.component';
+import { BrowseDatasetsComponent } from './_pages/browse-datasets/browse-datasets.component';
+import { BrowsePredictorsComponent } from './_pages/browse-predictors/browse-predictors.component';
+import { PredictComponent } from './_pages/predict/predict.component';
@NgModule({
declarations: [
AppComponent,
- LoginPageComponent,
- RegisterPageComponent,
- OnlyAuthorizedComponent,
DatasetLoadComponent,
AddModelComponent,
- LoginModalComponent
+ LoginModalComponent,
+ RegisterModalComponent,
+ HomeComponent,
+ NavbarComponent,
+ ItemPredictorComponent,
+ ItemDatasetComponent,
+ CarouselComponent,
+ SettingsComponent,
+ ProfileComponent,
+ MyPredictorsComponent,
+ MyDatasetsComponent,
+ MyModelsComponent,
+ BrowseDatasetsComponent,
+ BrowsePredictorsComponent,
+ PredictComponent
],
imports: [
BrowserModule,
@@ -35,7 +59,9 @@ import { ReactiveFormsModule } from '@angular/forms';
NgbModule,
BrowserAnimationsModule,
MaterialModule,
- ReactiveFormsModule
+ ReactiveFormsModule,
+ MatSliderModule,
+ MatIconModule
],
providers: [],
bootstrap: [AppComponent]