aboutsummaryrefslogtreecommitdiff
path: root/frontend/src
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src')
-rw-r--r--frontend/src/app/_data/Model.ts53
-rw-r--r--frontend/src/app/_elements/dataset-load/dataset-load.component.css0
-rw-r--r--frontend/src/app/_elements/dataset-load/dataset-load.component.html42
-rw-r--r--frontend/src/app/_elements/dataset-load/dataset-load.component.spec.ts25
-rw-r--r--frontend/src/app/_elements/dataset-load/dataset-load.component.ts54
-rw-r--r--frontend/src/app/_modals/login-modal/login-modal.component.css0
-rw-r--r--frontend/src/app/_modals/login-modal/login-modal.component.html49
-rw-r--r--frontend/src/app/_modals/login-modal/login-modal.component.spec.ts25
-rw-r--r--frontend/src/app/_modals/login-modal/login-modal.component.ts51
-rw-r--r--frontend/src/app/_pages/add-model/add-model.component.css0
-rw-r--r--frontend/src/app/_pages/add-model/add-model.component.html189
-rw-r--r--frontend/src/app/_pages/add-model/add-model.component.spec.ts25
-rw-r--r--frontend/src/app/_pages/add-model/add-model.component.ts32
-rw-r--r--frontend/src/app/_pages/login-page/login-page.component.html38
-rw-r--r--frontend/src/app/_pages/login-page/login-page.component.ts55
-rw-r--r--frontend/src/app/_pages/register-page/register-page.component.ts16
-rw-r--r--frontend/src/app/_services/auth.service.ts2
-rw-r--r--frontend/src/app/app-routing.module.ts9
-rw-r--r--frontend/src/app/app.module.ts17
-rw-r--r--frontend/src/app/material.module.ts18
-rw-r--r--frontend/src/custom-theme.scss35
-rw-r--r--frontend/src/index.html5
-rw-r--r--frontend/src/styles.css6
23 files changed, 703 insertions, 43 deletions
diff --git a/frontend/src/app/_data/Model.ts b/frontend/src/app/_data/Model.ts
new file mode 100644
index 00000000..216e1c36
--- /dev/null
+++ b/frontend/src/app/_data/Model.ts
@@ -0,0 +1,53 @@
+export default class Model {
+ constructor(
+ public name: string = 'Novi model',
+ public description: string = '',
+ public dateCreated: Date = new Date(),
+ public datasetId?: number,
+
+ //Test set settings
+ public inputColumns: number[] = [0],
+ public columnToPredict: number = 1,
+ public randomTestSet: boolean = true,
+ public randomTestSetDistribution: number = 0.10, //0.1-0.9 (10% - 90%)
+
+ // Neural net training settings
+ public type: ANNType = ANNType.FullyConnected,
+ public encoding: Encoding = Encoding.Label,
+ public optimizer: Optimizer = Optimizer.Adam,
+ public lossFunction: LossFunction = LossFunction.MeanSquaredError,
+ public inputNeurons: number = 1,
+ public hiddenLayerNeurons: number = 1,
+ public hiddenLayers: number = 1,
+ public batchSize: number = 5,
+ public inputLayerActivationFunction: ActivationFunction = ActivationFunction.Sigmoid,
+ public hiddenLayerActivationFunction: ActivationFunction = ActivationFunction.Sigmoid,
+ public outputLayerActivationFunction: ActivationFunction = ActivationFunction.Sigmoid
+ ) { }
+}
+
+export enum ANNType {
+ FullyConnected = 'potpuno povezana',
+ Convolutional = 'konvoluciona'
+}
+
+export enum Encoding {
+ Label = 'label',
+ OneHot = 'one hot'
+}
+
+export enum ActivationFunction {
+ Relu = 'relu',
+ Sigmoid = 'sigmoid',
+ Tanh = 'tanh',
+ Linear = 'linear'
+}
+
+export enum LossFunction {
+ BinaryCrossEntropy = 'binary_crossentropy',
+ MeanSquaredError = 'mean_squared_error'
+}
+
+export enum Optimizer {
+ Adam = 'adam'
+} \ No newline at end of file
diff --git a/frontend/src/app/_elements/dataset-load/dataset-load.component.css b/frontend/src/app/_elements/dataset-load/dataset-load.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.css
diff --git a/frontend/src/app/_elements/dataset-load/dataset-load.component.html b/frontend/src/app/_elements/dataset-load/dataset-load.component.html
new file mode 100644
index 00000000..c89add43
--- /dev/null
+++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.html
@@ -0,0 +1,42 @@
+<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>
+
+ <input id="fileInput" class="form-control mb-5" type="file" class="upload" (change)="changeListener($event)" accept=".csv">
+
+ <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>
+
+ <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>
+
+ <div *ngIf="csvRecords.length > 0" id="info">
+ . . . <br>
+ {{rowsNumber}} x {{colsNumber}}
+ </div>
+
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_elements/dataset-load/dataset-load.component.spec.ts b/frontend/src/app/_elements/dataset-load/dataset-load.component.spec.ts
new file mode 100644
index 00000000..5601b57b
--- /dev/null
+++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DatasetLoadComponent } from './dataset-load.component';
+
+describe('DatasetLoadComponent', () => {
+ let component: DatasetLoadComponent;
+ let fixture: ComponentFixture<DatasetLoadComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ DatasetLoadComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DatasetLoadComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_elements/dataset-load/dataset-load.component.ts b/frontend/src/app/_elements/dataset-load/dataset-load.component.ts
new file mode 100644
index 00000000..843a5709
--- /dev/null
+++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.ts
@@ -0,0 +1,54 @@
+import { Component, ViewChild } from '@angular/core';
+import { NgxCsvParser, NgxCSVParserError } from 'ngx-csv-parser';
+
+@Component({
+ selector: 'app-dataset-load',
+ templateUrl: './dataset-load.component.html',
+ styleUrls: ['./dataset-load.component.css']
+})
+export class DatasetLoadComponent {
+
+ delimiter: string = "";
+ delimiterOptions: Array<string> = [",", ";", "\t", "razmak", "|"]; //podrazumevano ","
+
+ hasHeader: boolean = true;
+
+ slice: string = "";
+
+ csvRecords: any[] = [];
+ files: any[] = [];
+ rowsNumber: number = 0;
+ colsNumber: number = 0;
+
+ constructor(private ngxCsvParser: NgxCsvParser) {
+ }
+
+ @ViewChild('fileImportInput', { static: false }) fileImportInput: any;
+
+ changeListener($event: any): void {
+ this.files = $event.srcElement.files;
+ this.update();
+ }
+
+ update() {
+
+ if (this.files.length < 1)
+ return;
+
+ this.ngxCsvParser.parse(this.files[0], { header: false, delimiter: (this.delimiter == "razmak") ? " " : (this.delimiter == "") ? "," : this.delimiter})
+ .pipe().subscribe((result) => {
+
+ //console.log('Result', result);
+ if (result.constructor === Array) {
+ this.csvRecords = result;
+ if (this.hasHeader)
+ this.rowsNumber = this.csvRecords.length - 1;
+ else
+ this.rowsNumber = this.csvRecords.length;
+ this.colsNumber = this.csvRecords[0].length;
+ }
+ }, (error: NgxCSVParserError) => {
+ console.log('Error', error);
+ });
+ }
+}
diff --git a/frontend/src/app/_modals/login-modal/login-modal.component.css b/frontend/src/app/_modals/login-modal/login-modal.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_modals/login-modal/login-modal.component.css
diff --git a/frontend/src/app/_modals/login-modal/login-modal.component.html b/frontend/src/app/_modals/login-modal/login-modal.component.html
new file mode 100644
index 00000000..22f50de2
--- /dev/null
+++ b/frontend/src/app/_modals/login-modal/login-modal.component.html
@@ -0,0 +1,49 @@
+<!-- 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>
+ <div class="modal-body px-5" style="color:#003459">
+ <h1 class="text-center mt-2 mb-4">Prijavite se</h1>
+ <form>
+ <!-- Korisnicko ime -->
+ <div class="form-outline mb-3">
+ <label class="form-label" for="username">Korisničko ime</label>
+ <input [(ngModel)]="username" name="username" type="text" id="username"
+ class="form-control form-control" placeholder="Unesite korisničko ime..." />
+ </div>
+ <!-- Lozinka -->
+ <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" placeholder="Unesite lozinku..." />
+ </div>
+
+ <div class="text-center text-lg-start mt-5 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>
+ </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>
+ </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>
+ </p>
+ </div>
+ </div>
+ </div>
+</div>
+
+
diff --git a/frontend/src/app/_modals/login-modal/login-modal.component.spec.ts b/frontend/src/app/_modals/login-modal/login-modal.component.spec.ts
new file mode 100644
index 00000000..7d0d526a
--- /dev/null
+++ b/frontend/src/app/_modals/login-modal/login-modal.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { LoginModalComponent } from './login-modal.component';
+
+describe('LoginModalComponent', () => {
+ let component: LoginModalComponent;
+ let fixture: ComponentFixture<LoginModalComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ LoginModalComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(LoginModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_modals/login-modal/login-modal.component.ts b/frontend/src/app/_modals/login-modal/login-modal.component.ts
new file mode 100644
index 00000000..3a6fd8f1
--- /dev/null
+++ b/frontend/src/app/_modals/login-modal/login-modal.component.ts
@@ -0,0 +1,51 @@
+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',
+ templateUrl: './login-modal.component.html',
+ styleUrls: ['./login-modal.component.css']
+})
+export class LoginModalComponent implements OnInit {
+
+ loginModal: any;
+ username: string = '';
+ password: string = '';
+
+ public wrongCreds: boolean = false; //RAZMOTRITI
+
+ constructor(
+ private authService: AuthService,
+ private cookie: CookieService,
+ private router: Router
+ ) { }
+
+ 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() {
+
+ }
+}
diff --git a/frontend/src/app/_pages/add-model/add-model.component.css b/frontend/src/app/_pages/add-model/add-model.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_pages/add-model/add-model.component.css
diff --git a/frontend/src/app/_pages/add-model/add-model.component.html b/frontend/src/app/_pages/add-model/add-model.component.html
new file mode 100644
index 00000000..bc292bb9
--- /dev/null
+++ b/frontend/src/app/_pages/add-model/add-model.component.html
@@ -0,0 +1,189 @@
+<div class="container p-3" style="background-color: rgb(249, 251, 253); min-height: 100%;">
+
+ <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>
+
+ <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>
+ </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>
+ </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>-->
+
+ <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="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="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="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="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="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="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>
+ </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>
+ </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 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.spec.ts b/frontend/src/app/_pages/add-model/add-model.component.spec.ts
new file mode 100644
index 00000000..2926e1c4
--- /dev/null
+++ b/frontend/src/app/_pages/add-model/add-model.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AddModelComponent } from './add-model.component';
+
+describe('AddModelComponent', () => {
+ let component: AddModelComponent;
+ let fixture: ComponentFixture<AddModelComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ AddModelComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AddModelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_pages/add-model/add-model.component.ts b/frontend/src/app/_pages/add-model/add-model.component.ts
new file mode 100644
index 00000000..3cb47d61
--- /dev/null
+++ b/frontend/src/app/_pages/add-model/add-model.component.ts
@@ -0,0 +1,32 @@
+import { Component, OnInit } from '@angular/core';
+import Model from 'src/app/_data/Model';
+import { ANNType, Encoding, ActivationFunction, LossFunction, Optimizer } from 'src/app/_data/Model';
+
+@Component({
+ selector: 'app-add-model',
+ templateUrl: './add-model.component.html',
+ styleUrls: ['./add-model.component.css']
+})
+export class AddModelComponent implements OnInit {
+
+ newModel: Model
+
+ ANNType = ANNType;
+ Encoding = Encoding;
+ ActivationFunction = ActivationFunction;
+ LossFunction = LossFunction;
+ Optimizer = Optimizer;
+ Object = Object;
+
+ constructor() {
+ this.newModel = new Model();
+ }
+
+ ngOnInit(): void {
+ }
+
+ addModel() {
+ //TODO
+ }
+
+}
diff --git a/frontend/src/app/_pages/login-page/login-page.component.html b/frontend/src/app/_pages/login-page/login-page.component.html
index 906eaba6..8deb5290 100644
--- a/frontend/src/app/_pages/login-page/login-page.component.html
+++ b/frontend/src/app/_pages/login-page/login-page.component.html
@@ -1,18 +1,33 @@
+<!--<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;">
- <!-- TODO : <app-navbar [activeNav]="'login'"></app-navbar>-->
-
<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>
- <!-- Email input -->
<div class="form-outline mb-4">
- <label class="form-label" for="email">Email adresa</label>
- <input [(ngModel)]="email" name="email" type="email" id="email" class="form-control form-control-lg"
- placeholder="Unesite email adresu..." />
+ <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>
- <!-- Password input -->
<div class="form-outline mb-3">
<label class="form-label" for="password">Lozinka</label>
<input [(ngModel)]="password" name="password" type="password" id="password"
@@ -20,17 +35,15 @@
</div>
<div class="text-center text-lg-start mt-4 pt-2">
- <!-- Pogresna lozinka -->
<p *ngIf="wrongCreds" class="small fw-bold mt-2 pt-1 mb-0 text-danger">Lozinka ili e-mail su pogrešni
</p>
- <!-- Nepotvrdjena registracija
- <p *ngIf="notApproved" class="small fw-bold mt-2 pt-1 mb-0 text-danger">Vaša registracija još uvek nije potvrđena</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>
@@ -38,6 +51,5 @@
</form>
</div>
- <!-- TODO: <app-footer></app-footer>-->
-
-</div> \ No newline at end of file
+</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
index f8b429e3..e5366283 100644
--- a/frontend/src/app/_pages/login-page/login-page.component.ts
+++ b/frontend/src/app/_pages/login-page/login-page.component.ts
@@ -1,40 +1,63 @@
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']
+ styleUrls: ['./login-page.component.css'],
+
})
-export class LoginPageComponent implements OnInit {
- email: string = '';
+export class LoginPageComponent{
+
+ modalRef?: MDBModalRef;
+
+ //email: string = '';
+ username: string = '';
password: string = '';
public wrongCreds: boolean = false; //RAZMOTRITI
//public notApproved: boolean = false; //RAZMOTRITI
- pattEmail: RegExp = /^[a-zA-Z0-9]+([\.\-\+][a-zA-Z0-9]+)*\@([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}$/;
+ formModal: any;
constructor(
private authService: AuthService,
- private cookie: CookieService
+ 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")
+ );
}
- onSubmit() {
- if (!this.pattEmail.test(this.email)) {
- console.warn('Bad email!');
- return;
- }
- else {
- this.authService.login(this.email, this.password).subscribe((response) => {
- console.log(response);
- this.cookie.set('token', response);
- })
- }
+ 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/register-page/register-page.component.ts b/frontend/src/app/_pages/register-page/register-page.component.ts
index e8d4c036..712fc55e 100644
--- a/frontend/src/app/_pages/register-page/register-page.component.ts
+++ b/frontend/src/app/_pages/register-page/register-page.component.ts
@@ -104,7 +104,7 @@ export class RegisterPageComponent implements OnInit {
this.firstNameValidation();
this.lastNameValidation();
- this.nickNameValidation();
+ //this.nickNameValidation();
this.emailValidation();
this.passwordValidation();
@@ -114,19 +114,21 @@ export class RegisterPageComponent implements OnInit {
let user = {
firstName: this.firstName,
lastName: this.lastName,
- nickName: this.nickName,
- email: this.email,
- password: this.pass1
+ username: this.nickName,
+ password: this.pass1,
+ email: this.email
}
this.authService.register(user)
.subscribe(
(response) => {
console.log(response);
- /*if ()
+ if (response === 'User added')
this.router.navigate(['/login']); //registracija uspesna, idi na login
- else if ()
- alert('Nalog sa unetim email-om već postoji!');*/
+ 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!');
}
);
}
diff --git a/frontend/src/app/_services/auth.service.ts b/frontend/src/app/_services/auth.service.ts
index 7129b95b..c96c2dae 100644
--- a/frontend/src/app/_services/auth.service.ts
+++ b/frontend/src/app/_services/auth.service.ts
@@ -18,7 +18,7 @@ export class AuthService {
}
register(user: any) {
- return this.http.post(`${API_SETTINGS.apiURL}/auth/register`, user);
+ return this.http.post(`${API_SETTINGS.apiURL}/auth/register`, { ...user }, { responseType: 'text' });
}
isAuthenticated(): boolean {
diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts
index 1868e56c..cd86ef5c 100644
--- a/frontend/src/app/app-routing.module.ts
+++ b/frontend/src/app/app-routing.module.ts
@@ -1,15 +1,20 @@
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 { AuthGuardService } from './_services/auth-guard.service';
+import { AddModelComponent } from './_pages/add-model/add-model.component';
+import { LoginModalComponent } from './_modals/login-modal/login-modal.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: 'only-authorized', component: OnlyAuthorizedComponent, canActivate: [AuthGuardService] },
+ { path: 'add-model', component: AddModelComponent },
+ { path: 'login-modal-test', component: LoginModalComponent }
];
@NgModule({
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index 9ccd7ddb..d95252ad 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -9,20 +9,33 @@ 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 { MaterialModule } from './material.module';
+import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
declarations: [
AppComponent,
LoginPageComponent,
RegisterPageComponent,
- OnlyAuthorizedComponent
+ OnlyAuthorizedComponent,
+ DatasetLoadComponent,
+ AddModelComponent,
+ LoginModalComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
HttpClientModule,
- NgbModule
+ NgbModule,
+ BrowserAnimationsModule,
+ MaterialModule,
+ ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
diff --git a/frontend/src/app/material.module.ts b/frontend/src/app/material.module.ts
new file mode 100644
index 00000000..e85419ee
--- /dev/null
+++ b/frontend/src/app/material.module.ts
@@ -0,0 +1,18 @@
+import { NgModule } from '@angular/core';
+
+import { MatDialogModule } from '@angular/material/dialog';
+import { MatButtonModule } from '@angular/material/button';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { MatCheckboxModule } from '@angular/material/checkbox';
+
+@NgModule({
+ exports: [
+ MatDialogModule,
+ MatButtonModule,
+ MatFormFieldModule,
+ MatInputModule,
+ MatCheckboxModule
+ ]
+})
+export class MaterialModule {} \ No newline at end of file
diff --git a/frontend/src/custom-theme.scss b/frontend/src/custom-theme.scss
new file mode 100644
index 00000000..a6538c37
--- /dev/null
+++ b/frontend/src/custom-theme.scss
@@ -0,0 +1,35 @@
+
+// Custom Theming for Angular Material
+// For more information: https://material.angular.io/guide/theming
+@use '@angular/material' as mat;
+// Plus imports for other components in your app.
+
+// Include the common styles for Angular Material. We include this here so that you only
+// have to load a single css file for Angular Material in your app.
+// Be sure that you only ever include this mixin once!
+@include mat.core();
+
+// Define the palettes for your theme using the Material Design palettes available in palette.scss
+// (imported above). For each palette, you can optionally specify a default, lighter, and darker
+// hue. Available color palettes: https://material.io/design/color/
+$frontend-primary: mat.define-palette(mat.$indigo-palette);
+$frontend-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
+
+// The warn palette is optional (defaults to red).
+$frontend-warn: mat.define-palette(mat.$red-palette);
+
+// Create the theme object. A theme consists of configurations for individual
+// theming systems such as "color" or "typography".
+$frontend-theme: mat.define-light-theme((
+ color: (
+ primary: $frontend-primary,
+ accent: $frontend-accent,
+ warn: $frontend-warn,
+ )
+));
+
+// Include theme styles for core and each component used in your app.
+// Alternatively, you can import and @include the theme mixins for each component
+// that you are using.
+@include mat.all-component-themes($frontend-theme);
+
diff --git a/frontend/src/index.html b/frontend/src/index.html
index 3af61ec9..b3b6eb54 100644
--- a/frontend/src/index.html
+++ b/frontend/src/index.html
@@ -6,8 +6,11 @@
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
+ <link rel="preconnect" href="https://fonts.gstatic.com">
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
-<body>
+<body class="mat-typography">
<app-root></app-root>
</body>
</html>
diff --git a/frontend/src/styles.css b/frontend/src/styles.css
index 90d4ee00..8997c10e 100644
--- a/frontend/src/styles.css
+++ b/frontend/src/styles.css
@@ -1 +1,5 @@
-/* You can add global styles to this file, and also import other style files */
+/* You can add global styles to this file, and also import other style files
+
+html, body { height: 100%; }
+body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
+*/ \ No newline at end of file