aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/api/api/Controllers/FileController.cs103
-rw-r--r--backend/api/api/Controllers/PredictorController.cs10
-rw-r--r--backend/api/api/Models/FileModel.cs1
-rw-r--r--backend/api/api/Models/PredictorColumns.cs8
-rw-r--r--backend/api/api/Services/PredictorService.cs2
-rw-r--r--backend/microservice/api/ml_service.py33
-rw-r--r--frontend/angular.json8
-rw-r--r--frontend/src/app/Shared.ts25
-rw-r--r--frontend/src/app/_elements/item-predictor/item-predictor.component.ts3
-rw-r--r--frontend/src/app/_elements/navbar/navbar.component.ts4
-rw-r--r--frontend/src/app/_modals/alert-dialog/alert-dialog.component.css0
-rw-r--r--frontend/src/app/_modals/alert-dialog/alert-dialog.component.html7
-rw-r--r--frontend/src/app/_modals/alert-dialog/alert-dialog.component.spec.ts25
-rw-r--r--frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts28
-rw-r--r--frontend/src/app/_modals/login-modal/login-modal.component.html2
-rw-r--r--frontend/src/app/_modals/login-modal/login-modal.component.ts5
-rw-r--r--frontend/src/app/_modals/register-modal/register-modal.component.ts12
-rw-r--r--frontend/src/app/_pages/add-model/add-model.component.ts18
-rw-r--r--frontend/src/app/_pages/browse-predictors/browse-predictors.component.html2
-rw-r--r--frontend/src/app/_pages/browse-predictors/browse-predictors.component.ts2
-rw-r--r--frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts8
-rw-r--r--frontend/src/app/_pages/my-models/my-models.component.ts3
-rw-r--r--frontend/src/app/_pages/my-predictors/my-predictors.component.html2
-rw-r--r--frontend/src/app/_pages/my-predictors/my-predictors.component.ts37
-rw-r--r--frontend/src/app/_pages/predict/predict.component.html40
-rw-r--r--frontend/src/app/_pages/predict/predict.component.ts16
-rw-r--r--frontend/src/app/_pages/profile/profile.component.ts13
-rw-r--r--frontend/src/app/_services/predictors.service.ts11
-rw-r--r--frontend/src/app/app.module.ts10
-rw-r--r--frontend/src/app/material.module.ts7
30 files changed, 351 insertions, 94 deletions
diff --git a/backend/api/api/Controllers/FileController.cs b/backend/api/api/Controllers/FileController.cs
index 0fe8415b..d29c5676 100644
--- a/backend/api/api/Controllers/FileController.cs
+++ b/backend/api/api/Controllers/FileController.cs
@@ -4,6 +4,7 @@ using api.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
+
namespace api.Controllers
{
[Route("api/[controller]")]
@@ -11,6 +12,7 @@ namespace api.Controllers
public class FileController : ControllerBase
{
private string[] permittedExtensions = { ".csv" };
+ private string[] permittedExtensionsH5 = { ".h5" };//niz da bi dodali h4 itd
private readonly IConfiguration _configuration;
private IJwtToken _token;
private IFileService _fileservice;
@@ -22,6 +24,77 @@ namespace api.Controllers
}
+ [HttpPost("h5")]
+ [Authorize(Roles = "User,Guest")]
+ public async Task<ActionResult<string>> H5Upload([FromForm] IFormFile file)
+ {
+
+ //get username from jwtToken
+ string uploaderId;
+ string folderName;
+ var header = Request.Headers[HeaderNames.Authorization];
+ if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
+ {
+
+ var scheme = headerValue.Scheme;
+ var parameter = headerValue.Parameter;
+ uploaderId = _token.TokenToId(parameter);
+ if (uploaderId == null)
+ return null;
+ }
+ else
+ return BadRequest();
+ if (uploaderId == "")
+ {
+ folderName = "TempFiles";
+ }
+ else
+ {
+ folderName = "UploadedFiles";
+ }
+
+
+ //Check filetype
+ var filename = file.FileName;
+ var ext = Path.GetExtension(filename).ToLowerInvariant();
+ var name = Path.GetFileNameWithoutExtension(filename).ToLowerInvariant();
+ if (string.IsNullOrEmpty(ext) || !permittedExtensionsH5.Contains(ext))
+ {
+ return BadRequest("Wrong file type");
+ }
+ var folderPath = Path.Combine(Directory.GetCurrentDirectory(), folderName, uploaderId);
+ //Check Directory
+ if (!Directory.Exists(folderPath))
+ {
+ Directory.CreateDirectory(folderPath);
+ }
+ //Index file if same filename
+ var fullPath = Path.Combine(folderPath, filename);
+ int i = 0;
+
+ while (System.IO.File.Exists(fullPath))
+ {
+ i++;
+ fullPath = Path.Combine(folderPath, name + i.ToString() + ext);
+ }
+
+
+ //Write file
+ using (var stream = new FileStream(fullPath, FileMode.Create))
+ {
+ await file.CopyToAsync(stream);
+ }
+ FileModel fileModel = new FileModel();
+ fileModel.type = "h5";
+ fileModel.path = fullPath;
+ fileModel.uploaderId = uploaderId;
+ fileModel.date = DateTime.Now.ToUniversalTime();
+ fileModel = _fileservice.Create(fileModel);
+
+
+ return Ok(fileModel);
+ }
+
[HttpPost("Csv")]
[Authorize(Roles = "User,Guest")]
@@ -81,6 +154,7 @@ namespace api.Controllers
await file.CopyToAsync(stream);
}
FileModel fileModel= new FileModel();
+ fileModel.type = "csv";
fileModel.path=fullPath;
fileModel.uploaderId= uploaderId;
fileModel.date = DateTime.Now.ToUniversalTime();
@@ -90,6 +164,35 @@ namespace api.Controllers
return Ok(fileModel);
}
+
+ //msm generalno moze da se koristi Download samo
+ [HttpGet("downloadh5")]
+ [Authorize(Roles = "User,Guest")]
+ public async Task<ActionResult> DownloadH5(string id)
+ {
+ //Get Username
+ string uploaderId;
+ var header = Request.Headers[HeaderNames.Authorization];
+ if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
+ {
+
+ var scheme = headerValue.Scheme;
+ var parameter = headerValue.Parameter;
+ uploaderId = _token.TokenToId(parameter);
+ if (uploaderId == null)
+ return null;
+ }
+ else
+ return BadRequest();
+
+ string filePath = _fileservice.GetFilePath(id, uploaderId);
+ if (filePath == null)
+ return BadRequest();
+
+ return File(System.IO.File.ReadAllBytes(filePath), "application/octet-stream", Path.GetFileName(filePath));
+
+ }
+
[HttpGet("Download")]
[Authorize(Roles = "User,Guest")]
public async Task<ActionResult> DownloadFile(string id)
diff --git a/backend/api/api/Controllers/PredictorController.cs b/backend/api/api/Controllers/PredictorController.cs
index cdc14632..161271e2 100644
--- a/backend/api/api/Controllers/PredictorController.cs
+++ b/backend/api/api/Controllers/PredictorController.cs
@@ -77,7 +77,7 @@ namespace api.Controllers
// GET api/<PredictorController>/getpredictor/{name}
[HttpGet("getpredictor/{id}")]
- [Authorize(Roles = "User")]
+ [Authorize(Roles = "User,Guest")]
public ActionResult<Predictor> GetPredictor(string id)
{
string username;
@@ -188,8 +188,8 @@ namespace api.Controllers
// POST api/<PredictorController>/usepredictor {predictor,inputs}
[HttpPost("usepredictor/{id}")]
- [Authorize(Roles = "User")]
- public ActionResult UsePredictor(String id, [FromBody] String[] inputs)
+ [Authorize(Roles = "User,Guest")]
+ public ActionResult UsePredictor(String id, [FromBody] PredictorColumns[] inputs)
{
string username;
@@ -207,8 +207,8 @@ namespace api.Controllers
Predictor predictor = _predictorService.GetPredictor(username, id);
- foreach(String i in inputs)
- Debug.WriteLine(i);
+ foreach(PredictorColumns i in inputs)
+ Debug.WriteLine(i.value.ToString());
return NoContent();
}
diff --git a/backend/api/api/Models/FileModel.cs b/backend/api/api/Models/FileModel.cs
index 1043309d..47b12110 100644
--- a/backend/api/api/Models/FileModel.cs
+++ b/backend/api/api/Models/FileModel.cs
@@ -8,6 +8,7 @@ namespace api.Models
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string _id { get; set; }
+ public string type { get; set; }
public string uploaderId { get; set; }
public string path { get; set; }
[BsonDateTimeOptions(Kind = DateTimeKind.Utc)]
diff --git a/backend/api/api/Models/PredictorColumns.cs b/backend/api/api/Models/PredictorColumns.cs
new file mode 100644
index 00000000..82f3e979
--- /dev/null
+++ b/backend/api/api/Models/PredictorColumns.cs
@@ -0,0 +1,8 @@
+namespace api.Models
+{
+ public class PredictorColumns
+ {
+ public String name { get; set; }
+ public String value { get; set; }
+ }
+}
diff --git a/backend/api/api/Services/PredictorService.cs b/backend/api/api/Services/PredictorService.cs
index 01bc8359..b15255ac 100644
--- a/backend/api/api/Services/PredictorService.cs
+++ b/backend/api/api/Services/PredictorService.cs
@@ -42,7 +42,7 @@ namespace api.Services
}
public Predictor GetPredictor(string username, string id)
{
- return _predictor.Find(predictor => predictor.username == username && predictor._id == id).FirstOrDefault();
+ return _predictor.Find(predictor => predictor._id == id && (predictor.username == username || predictor.isPublic == true)).FirstOrDefault();
}
//last private models
diff --git a/backend/microservice/api/ml_service.py b/backend/microservice/api/ml_service.py
index b264b428..73b191da 100644
--- a/backend/microservice/api/ml_service.py
+++ b/backend/microservice/api/ml_service.py
@@ -205,21 +205,26 @@ def train(dataset, params, callback):
if(problem_type=='multi-klasifikacioni'):
func=params['hiddenLayerActivationFunctions']
- funcFirst=func.pop(0)
- inputDim = len(data.columns) - 1
- classifier=tf.keras.Sequential(units=hidden_layer_neurons,input_dim=inputDim,activation=funcFirst)
- for f in func:
- classifier.add(tf.keras.layers.Dense(units=hidden_layer_neurons,activation=func))
output_func = params["outputLayerActivationFunction"]
- numberofclasses=len(output_column.unique())
- classifier.add(tf.keras.layers.Dense(units=numberofclasses,activation=output_func))
-
optimizer = params["optimizer"]
metrics=params['metrics']
loss_func=params["lossFunction"]
- classifier.compile(optimizer=optimizer, loss=loss_func,metrics=metrics)
batch_size = params["batchSize"]
epochs = params["epochs"]
+ inputDim = len(data.columns) - 1
+
+ classifier=tf.keras.Sequential()
+
+ classifier.add(tf.keras.layers.Dense(units=len(data.columns),input_dim=inputDim))#input layer
+
+ for f in func:#hidden layers
+ classifier.add(tf.keras.layers.Dense(units=hidden_layer_neurons,activation=f))
+
+ numberofclasses=len(output_column.unique())
+ classifier.add(tf.keras.layers.Dense(units=numberofclasses,activation=output_func))#output layer
+
+ classifier.compile(optimizer=optimizer, loss=loss_func,metrics=metrics)
+
history=classifier.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, callbacks=callback(x_test, y_test))
else:
classifier=tf.keras.Sequential()
@@ -227,10 +232,12 @@ def train(dataset, params, callback):
for func in params["hiddenLayerActivationFunctions"]:
classifier.add(tf.keras.layers.Dense(units=hidden_layer_neurons,activation=func))
output_func = params["outputLayerActivationFunction"]
+
if(problem_type!="regresioni"):
classifier.add(tf.keras.layers.Dense(units=1,activation=output_func))
else:
classifier.add(tf.keras.layers.Dense(units=1))
+
optimizer = params["optimizer"]
metrics=params['metrics']
loss_func=params["lossFunction"]
@@ -249,7 +256,10 @@ def train(dataset, params, callback):
elif(problem_type == "binarni-klasifikacioni"):
y_pred=classifier.predict(x_test)
y_pred=(y_pred>=0.5).astype('int')
-
+ elif(problem_type=='multi-klasifikacioni'):
+ y_pred=classifier.predict(x_test)
+ y_pred=np.argmax(y_pred,axis=1)
+
y_pred=y_pred.flatten()
result=pd.DataFrame({"Actual":y_test,"Predicted":y_pred})
classifier.save("temp/"+model_name, save_format='h5')
@@ -323,6 +333,9 @@ def train(dataset, params, callback):
"adj_r2" : adj_r2
}
elif(problem_type=="multi-klasifikacioni"):
+
+ cr=sm.classification_report(y_test, y_pred)
+ cm=sm.confusion_matrix(y_test,y_pred)
# https://www.kaggle.com/code/nkitgupta/evaluation-metrics-for-multi-class-classification/notebook
accuracy=metrics.accuracy_score(y_test, y_pred)
macro_averaged_precision=metrics.precision_score(y_test, y_pred, average = 'macro')
diff --git a/frontend/angular.json b/frontend/angular.json
index b1aaac3f..6653e4b1 100644
--- a/frontend/angular.json
+++ b/frontend/angular.json
@@ -41,13 +41,13 @@
"budgets": [
{
"type": "initial",
- "maximumWarning": "500kb",
- "maximumError": "1mb"
+ "maximumWarning": "2mb",
+ "maximumError": "4mb"
},
{
"type": "anyComponentStyle",
- "maximumWarning": "2kb",
- "maximumError": "4kb"
+ "maximumWarning": "10kb",
+ "maximumError": "15kb"
}
],
"fileReplacements": [
diff --git a/frontend/src/app/Shared.ts b/frontend/src/app/Shared.ts
index 31afb1a6..86e26687 100644
--- a/frontend/src/app/Shared.ts
+++ b/frontend/src/app/Shared.ts
@@ -1,9 +1,32 @@
+import { ElementRef } from "@angular/core";
+import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { AlertDialogComponent } from './_modals/alert-dialog/alert-dialog.component';
+
class Shared {
constructor(
public loggedIn: boolean,
public username: string = '',
- public photoId: string = '1'
+ public photoId: string = '1',
+ public dialog?: MatDialog
+ //public alertDialog?: ElementRef
) { }
+
+
+ openDialog(title: string, message: string): void {
+ console.log("USAO U OPEN DIALOG 1");
+
+ if (this.dialog) {
+ console.log("USAO U OPEN DIALOG 2");
+ const dialogRef = this.dialog.open(AlertDialogComponent, {
+ //width: '250px',
+ data: { title: title, message: message }
+ });
+ dialogRef.afterClosed().subscribe(res => {
+ //nesto
+ });
+ }
+ }
}
export default new Shared(false); \ No newline at end of file
diff --git a/frontend/src/app/_elements/item-predictor/item-predictor.component.ts b/frontend/src/app/_elements/item-predictor/item-predictor.component.ts
index 41d2ab9c..246032e0 100644
--- a/frontend/src/app/_elements/item-predictor/item-predictor.component.ts
+++ b/frontend/src/app/_elements/item-predictor/item-predictor.component.ts
@@ -17,8 +17,7 @@ export class ItemPredictorComponent implements OnInit {
}
openPredictor() {
- this.router.navigate(['predict/'+ '6245a5958a9c76c1bf7ff9b6']);
- //this.router.navigate(['predict'+this.predictor._id]);
+ this.router.navigate(['predict/'+ this.predictor._id]);
}
}
diff --git a/frontend/src/app/_elements/navbar/navbar.component.ts b/frontend/src/app/_elements/navbar/navbar.component.ts
index 2e4bde91..368508ed 100644
--- a/frontend/src/app/_elements/navbar/navbar.component.ts
+++ b/frontend/src/app/_elements/navbar/navbar.component.ts
@@ -3,6 +3,7 @@ import { Location } from '@angular/common';
import { AuthService } from '../../_services/auth.service';
import shared from 'src/app/Shared';
import { UserInfoService } from 'src/app/_services/user-info.service';
+import { MatDialog } from '@angular/material/dialog';
@Component({
selector: 'app-navbar',
@@ -14,7 +15,8 @@ export class NavbarComponent implements OnInit {
currentUrl: string;
shared = shared;
- constructor(public location: Location, private auth: AuthService, private userInfoService: UserInfoService) {
+ constructor(public location: Location, private auth: AuthService, private userInfoService: UserInfoService, private matDialog: MatDialog) {
+ shared.dialog = matDialog;
this.currentUrl = this.location.path();
this.location.onUrlChange(() => {
this.currentUrl = this.location.path();
diff --git a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.css b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.css
diff --git a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.html b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.html
new file mode 100644
index 00000000..82365193
--- /dev/null
+++ b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.html
@@ -0,0 +1,7 @@
+<h2 mat-dialog-title class="text-muted">{{data.title}}</h2>
+<div mat-dialog-content class="mt-4" style="color: rgb(81, 76, 76);">
+ {{data.message}}
+</div>
+<div mat-dialog-actions class="d-flex justify-content-center mt-4">
+ <button mat-button cdkFocusInitial (click)="onOkClick()" style="background-color: lightgray;">OK</button>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.spec.ts b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.spec.ts
new file mode 100644
index 00000000..a93fc493
--- /dev/null
+++ b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AlertDialogComponent } from './alert-dialog.component';
+
+describe('AlertDialogComponent', () => {
+ let component: AlertDialogComponent;
+ let fixture: ComponentFixture<AlertDialogComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ AlertDialogComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(AlertDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts
new file mode 100644
index 00000000..e15f3c6f
--- /dev/null
+++ b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts
@@ -0,0 +1,28 @@
+import { Component, OnInit } from '@angular/core';
+import { Inject} from '@angular/core';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material/dialog';
+
+interface DialogData {
+ title: string;
+ message: string;
+}
+
+@Component({
+ selector: 'app-alert-dialog',
+ templateUrl: './alert-dialog.component.html',
+ styleUrls: ['./alert-dialog.component.css']
+})
+export class AlertDialogComponent {
+
+ constructor(
+ public dialogRef: MatDialogRef<AlertDialogComponent>,
+ @Inject(MAT_DIALOG_DATA) public data: DialogData,
+ //public dialog: MatDialog
+ ) {}
+
+ onOkClick(): void {
+ this.dialogRef.close();
+ }
+
+
+}
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 d7836848..03048155 100644
--- a/frontend/src/app/_modals/login-modal/login-modal.component.html
+++ b/frontend/src/app/_modals/login-modal/login-modal.component.html
@@ -3,7 +3,7 @@
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<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>
+ <button #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>
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 c86c269a..e1535a25 100644
--- a/frontend/src/app/_modals/login-modal/login-modal.component.ts
+++ b/frontend/src/app/_modals/login-modal/login-modal.component.ts
@@ -4,6 +4,7 @@ import { CookieService } from 'ngx-cookie-service';
import { AuthService } from 'src/app/_services/auth.service';
import { UserInfoService } from 'src/app/_services/user-info.service';
import shared from '../../Shared';
+import {AfterViewInit, ElementRef} from '@angular/core';
@Component({
selector: 'app-login-modal',
@@ -12,6 +13,8 @@ import shared from '../../Shared';
})
export class LoginModalComponent implements OnInit {
+ @ViewChild('closeButton') closeButton?: ElementRef;
+
username: string = '';
password: string = '';
@@ -38,7 +41,7 @@ export class LoginModalComponent implements OnInit {
}
else {
this.authService.authenticate(response);
- (<HTMLSelectElement>document.getElementById('closeButton')).click();
+ (<HTMLSelectElement>this.closeButton?.nativeElement).click();
this.userInfoService.getUserInfo().subscribe((response) => {
shared.photoId = response.photoId;
});
diff --git a/frontend/src/app/_modals/register-modal/register-modal.component.ts b/frontend/src/app/_modals/register-modal/register-modal.component.ts
index 13ef7eba..05888589 100644
--- a/frontend/src/app/_modals/register-modal/register-modal.component.ts
+++ b/frontend/src/app/_modals/register-modal/register-modal.component.ts
@@ -1,6 +1,9 @@
import { Component, OnInit } from '@angular/core';
import { AuthService } from 'src/app/_services/auth.service';
import User from 'src/app/_data/User';
+import { DOCUMENT } from '@angular/common';
+import { Inject } from '@angular/core';
+import shared from 'src/app/Shared';
@Component({
selector: 'app-register-modal',
@@ -29,8 +32,11 @@ export class RegisterModalComponent implements OnInit {
pattEmail: RegExp = /^[a-zA-Z0-9]+([\.\-\+][a-zA-Z0-9]+)*\@([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}$/;
pattPassword: RegExp = /.{6,30}$/;
+ shared = shared;
+
constructor(
- private authService: AuthService
+ private authService: AuthService,
+ @Inject(DOCUMENT) document: Document
) { }
ngOnInit(): void {
@@ -149,11 +155,11 @@ export class RegisterModalComponent implements OnInit {
}, (error) => console.warn(error));
}
else if (response == 'Email Already Exists') {
- alert('Nalog sa unetim email-om već postoji!');
+ shared.openDialog("Greška!", "Nalog sa unetim email-om već postoji!");
(<HTMLSelectElement>document.getElementById('email')).focus();
}
else if (response == 'Username Already Exists') {
- alert('Nalog sa unetim korisničkim imenom već postoji!');
+ shared.openDialog("Greška!", "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.ts b/frontend/src/app/_pages/add-model/add-model.component.ts
index 2121dc3b..945a58b5 100644
--- a/frontend/src/app/_pages/add-model/add-model.component.ts
+++ b/frontend/src/app/_pages/add-model/add-model.component.ts
@@ -143,14 +143,14 @@ export class AddModelComponent implements OnInit {
this.models.addModel(this.newModel).subscribe((response) => {
callback(response);
}, (error) => {
- alert("Model sa unetim nazivom već postoji u Vašoj kolekciji.\nPromenite naziv modela i nastavite sa kreiranim datasetom.");
+ shared.openDialog("Neuspeo pokušaj!", "Model sa unetim nazivom već postoji u Vašoj kolekciji. Promenite naziv modela i nastavite sa kreiranim datasetom.");
}); //kraj addModel subscribe
}, (error) => {
- alert("Dataset sa unetim nazivom već postoji u Vašoj kolekciji.\nIzmenite naziv ili iskoristite postojeći dataset.");
+ shared.openDialog("Neuspeo pokušaj!", "Dataset sa unetim nazivom već postoji u Vašoj kolekciji. Izmenite naziv ili iskoristite postojeći dataset.");
}); //kraj addDataset subscribe
} //kraj treceg ifa
}, (error) => {
- //alert("greska uploadData");
+
}); //kraj uploadData subscribe
} //kraj drugog ifa
@@ -174,12 +174,12 @@ export class AddModelComponent implements OnInit {
this.models.addModel(this.newModel).subscribe((response) => {
callback(response);
}, (error) => {
- alert("Model sa unetim nazivom već postoji u Vašoj kolekciji.\nPromenite naziv modela i nastavite sa kreiranim datasetom.");
+ shared.openDialog("Neuspeo pokušaj!", "Model sa unetim nazivom već postoji u Vašoj kolekciji. Promenite naziv modela i nastavite sa kreiranim datasetom.");
});
}
}
else {
- alert("Molimo Vas da izaberete neki dataset iz kolekcije.");
+ shared.openDialog("Obaveštenje", "Molimo Vas da izaberete neki dataset iz kolekcije.");
}
}
@@ -213,21 +213,21 @@ export class AddModelComponent implements OnInit {
}
validationInputsOutput(): boolean {
if (this.newModel.inputColumns.length == 0 && this.newModel.columnToPredict == '') {
- alert("Molimo Vas da izaberete ulazne i izlazne kolone za mrežu.");
+ shared.openDialog("Neuspeo pokušaj!", "Molimo Vas da izaberete ulazne i izlazne kolone za mrežu.");
return false;
}
else if (this.newModel.inputColumns.length == 0) {
- alert("Molimo Vas da izaberete ulaznu kolonu/kolone za mrežu.");
+ shared.openDialog("Neuspeo pokušaj!", "Molimo Vas da izaberete ulaznu kolonu/kolone za mrežu.");
return false;
}
else if (this.newModel.columnToPredict == '') {
- alert("Molimo Vas da izaberete izlaznu kolonu za mrežu.");
+ shared.openDialog("Neuspeo pokušaj!", "Molimo Vas da izaberete izlaznu kolonu 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.");
+ shared.openDialog("Neuspeo pokušaj!", "Izabrali ste istu kolonu (" + colName + ") kao ulaznu i izlaznu iz mreže. Korigujte izbor.");
return false;
}
}
diff --git a/frontend/src/app/_pages/browse-predictors/browse-predictors.component.html b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.html
index a4ab6e2c..7b3e1bdb 100644
--- a/frontend/src/app/_pages/browse-predictors/browse-predictors.component.html
+++ b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.html
@@ -14,7 +14,7 @@
<div class="card-body">
<h3 class="card-title"><b>{{predictor.name}}</b></h3>
<p class="card-text">{{predictor.description}}</p>
- <a class="btn btn-primary" (click)="openPredictor(predictor._id)">Otvori</a>
+ <a class="btn btn-primary" (click)="openPredictor(predictor._id)">Iskoristi</a>
</div>
<div class="card-footer text-muted">
Kreirao: {{predictor.username}} <br>
diff --git a/frontend/src/app/_pages/browse-predictors/browse-predictors.component.ts b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.ts
index 4f96fc36..891b3cab 100644
--- a/frontend/src/app/_pages/browse-predictors/browse-predictors.component.ts
+++ b/frontend/src/app/_pages/browse-predictors/browse-predictors.component.ts
@@ -20,7 +20,7 @@ export class BrowsePredictorsComponent implements OnInit {
ngOnInit(): void {
}
openPredictor(id:string):void{
- this.router.navigateByUrl('/predict?id='+id);
+ this.router.navigate(['predict/'+id]);
};
}
diff --git a/frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts b/frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts
index b75decf2..fc146046 100644
--- a/frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts
+++ b/frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts
@@ -4,6 +4,7 @@ import Dataset from 'src/app/_data/Dataset';
import {Router} from '@angular/router'
import { JwtHelperService } from '@auth0/angular-jwt';
import { CookieService } from 'ngx-cookie-service';
+import shared from 'src/app/Shared';
@Component({
selector: 'app-filter-datasets',
@@ -12,6 +13,7 @@ import { CookieService } from 'ngx-cookie-service';
})
export class FilterDatasetsComponent implements OnInit {
+ shared = shared;
publicDatasets?: Dataset[];
term: string = "";
constructor(private datasets: DatasetsService,private router:Router, private cookie: CookieService) {
@@ -37,11 +39,9 @@ export class FilterDatasetsComponent implements OnInit {
if(name!=null && name!="")
this.datasets.addDataset(newDataset).subscribe((response:string)=>{
console.log(response);
- alert("Uspenso ste dodali dataset sa imenom "+newDataset.name);
+ shared.openDialog("Obaveštenje", "Uspešno ste dodali dataset sa nazivom " + newDataset.name);
},(error)=>{
- alert("Vec imate dataset sa istim imenom molim vas unesite drugo ime");
-
-
+ shared.openDialog("Obaveštenje", "U svojoj kolekciji već imate dataset sa ovim imenom. Molimo Vas da unesete drugo ime.");
});
};
diff --git a/frontend/src/app/_pages/my-models/my-models.component.ts b/frontend/src/app/_pages/my-models/my-models.component.ts
index bd6b0a2b..6086b1b1 100644
--- a/frontend/src/app/_pages/my-models/my-models.component.ts
+++ b/frontend/src/app/_pages/my-models/my-models.component.ts
@@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core';
+import shared from 'src/app/Shared';
import Model from 'src/app/_data/Model';
import { ModelsService } from 'src/app/_services/models.service';
@@ -38,7 +39,7 @@ deleteThisModel(model: Model): void{
this.getAllMyModels();
}, (error) =>{
if (error.error == "Model with name = {name} deleted") {
- alert("Greška pri brisanju modela!");
+ shared.openDialog("Obaveštenje", "Greška prilikom brisanja modela.");
}
});
diff --git a/frontend/src/app/_pages/my-predictors/my-predictors.component.html b/frontend/src/app/_pages/my-predictors/my-predictors.component.html
index d739f561..3746d35e 100644
--- a/frontend/src/app/_pages/my-predictors/my-predictors.component.html
+++ b/frontend/src/app/_pages/my-predictors/my-predictors.component.html
@@ -7,7 +7,7 @@
<app-item-predictor [predictor]="predictor"></app-item-predictor>
</div>
<div>
- <button (click)="delete()" mat-raised-button color="warn" style="min-width: 15rem;float: right" ><mat-icon>delete</mat-icon></button>
+ <button (click)="delete(predictor)" mat-raised-button color="warn" style="min-width: 15rem;float: right" ><mat-icon>delete</mat-icon></button>
</div>
</div>
diff --git a/frontend/src/app/_pages/my-predictors/my-predictors.component.ts b/frontend/src/app/_pages/my-predictors/my-predictors.component.ts
index 58daa44f..13cfdab2 100644
--- a/frontend/src/app/_pages/my-predictors/my-predictors.component.ts
+++ b/frontend/src/app/_pages/my-predictors/my-predictors.component.ts
@@ -1,5 +1,6 @@
import { Component, OnInit } from '@angular/core';
import Predictor from 'src/app/_data/Predictor';
+import { PredictorsService } from 'src/app/_services/predictors.service';
@Component({
selector: 'app-my-predictors',
@@ -7,22 +8,38 @@ import Predictor from 'src/app/_data/Predictor';
styleUrls: ['./my-predictors.component.css']
})
export class MyPredictorsComponent implements OnInit {
- predictors: Predictor[];
- constructor() {
- this.predictors = [
- new Predictor('Titanik', 'Opis titanik', ['K1', 'K2', 'K3', 'Ime', 'Preziveli'],'Preziveli'),
- new Predictor('Neki drugi set', 'opis', ['a', 'b', 'c'],'c'),
- 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')];
+ predictors: Predictor[] = [];
+ constructor(private predictorsS : PredictorsService) {
}
ngOnInit(): void {
+ this.getAllMyPredictors();
+
}
- delete(){
- confirm("IZABRANI MODEL ĆE BITI IZBRISAN")
+ delete(predictor: Predictor){
+ if(window.confirm("IZABRANI MODEL ĆE BITI IZBRISAN"))
+ {
+ this.predictorsS.deletePredictor(predictor).subscribe((response) => {
+ console.log("OBRISANOOO JEE", response);
+ //na kraju uspesnog
+ this.getAllMyPredictors();
+ }, (error) =>{
+ if (error.error == "Predictor with name = {name} deleted") {
+ alert("Greška pri brisanju modela!");
+ }
+ });
+ }
+
}
-
+
+ getAllMyPredictors(): void{
+ this.predictorsS.getMyPredictors().subscribe(m => {
+
+ this.predictors = m;
+ console.log(this.predictors);
+ });
+ }
}
diff --git a/frontend/src/app/_pages/predict/predict.component.html b/frontend/src/app/_pages/predict/predict.component.html
index bf4d9a1e..13afa8e4 100644
--- a/frontend/src/app/_pages/predict/predict.component.html
+++ b/frontend/src/app/_pages/predict/predict.component.html
@@ -18,7 +18,24 @@
<div>
<label for="output" class="col-sm-5 col-form-label">Opis prediktora: <b>{{predictor.description}}</b></label>
</div>
+
+
+ </div>
+ <br>
+ <label for="type" class="form-check-label" ><b>Informacije o prediktoru</b></label>
+ <div class="col-5 mt-2">
+ <label for="type" class="form-check-label" >Prediktor {{predictor.isPublic?"je":"nije"}} javni.</label>
+ </div>
+ <div class="col-5 mt-2">
+ <label for="type" class="form-check-label" >Prediktor {{predictor.accessibleByLink?"je":"nije"}} dostupan za deljenje.</label>
</div>
+ <br>
+ <div class="col-2">
+ <label for="dateCreated" class="col-form-label">Datum:</label>
+ <input type="text" class="form-control-plaintext" id="dateCreated" placeholder="--/--/--"
+ value="{{predictor.dateCreated | date: 'dd/MM/yyyy'}}" readonly>
+ </div>
+
<br>
<div >
@@ -28,7 +45,7 @@
<div *ngIf="predictor" class="form-group row mt-3 mb-2 d-flex justify-content-left">
<div *ngFor="let input of predictor.inputs; let i = index">
<label for="{{input}}" class="col-sm-2 col-form-label"><b>{{input}}</b></label>
- <input name="{{input}}" type="text" [(ngModel)]="inputs[i]" >
+ <input name="{{input}}" type="text" [(ngModel)]="inputs[i].value" >
</div>
@@ -41,28 +58,7 @@
<div>
<label for="output" class="col-sm-2 col-form-label">Izlaz: <b>{{predictor.output}}</b></label>
</div>
- <br>
- <br>
-
- <div class="col-5 mt-2">
- <label for="type" class="form-check-label">Da li je prediktor javan?</label>
- <input class="mx-3 form-check-input" type="checkbox" [(ngModel)]="predictor.isPublic"
- type="checkbox" value="">
- </div>
- <div class="col-5 mt-2">
- <label for="type" class="form-check-label">Da li je dostupan za deljenje?</label>
- <input class="mx-3 form-check-input" type="checkbox" [(ngModel)]="predictor.accessibleByLink"
- type="checkbox" value="" >
- </div>
- <br>
- <div class="col-2">
- <label for="dateCreated" class="col-form-label">Datum:</label>
- <input type="text" class="form-control-plaintext" id="dateCreated" placeholder="--/--/--"
- value="{{predictor.dateCreated | date: 'dd/MM/yyyy'}}" readonly>
- </div>
-
- <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;"
diff --git a/frontend/src/app/_pages/predict/predict.component.ts b/frontend/src/app/_pages/predict/predict.component.ts
index 71cf93ce..1c1c7425 100644
--- a/frontend/src/app/_pages/predict/predict.component.ts
+++ b/frontend/src/app/_pages/predict/predict.component.ts
@@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import Predictor from 'src/app/_data/Predictor';
import { PredictorsService } from 'src/app/_services/predictors.service';
+import shared from 'src/app/Shared';
@Component({
selector: 'app-predict',
@@ -10,7 +11,8 @@ import { PredictorsService } from 'src/app/_services/predictors.service';
})
export class PredictComponent implements OnInit {
- inputs : String[] = [];
+ inputs : Column[] = [];
+
predictor:Predictor;
constructor(private predictS : PredictorsService, private route: ActivatedRoute) {
@@ -22,6 +24,7 @@ export class PredictComponent implements OnInit {
this.predictS.getPredictor(url["id"]).subscribe(p => {
this.predictor = p;
+ this.predictor.inputs.forEach((p,index)=> this.inputs[index] = new Column(p, ""));
console.log(this.predictor);
})
});
@@ -29,9 +32,16 @@ export class PredictComponent implements OnInit {
usePredictor(): void{
this.predictS.usePredictor(this.predictor, this.inputs).subscribe(p => {
-
- alert("Prediktor je uspesno poslat na treniranje!");
+ shared.openDialog("Obaveštenje", "Prediktor je uspešno poslat na probu."); //pisalo je "na treniranje" ??
})
console.log(this.inputs);
}
}
+
+
+export class Column {
+ constructor(
+ public name : string,
+ public value : (number | string)){
+ }
+} \ No newline at end of file
diff --git a/frontend/src/app/_pages/profile/profile.component.ts b/frontend/src/app/_pages/profile/profile.component.ts
index 7a7796da..d055fad3 100644
--- a/frontend/src/app/_pages/profile/profile.component.ts
+++ b/frontend/src/app/_pages/profile/profile.component.ts
@@ -6,6 +6,7 @@ import { Router } from '@angular/router';
import { PICTURES } from 'src/app/_data/ProfilePictures';
import { Picture } from 'src/app/_data/ProfilePictures';
import shared from '../../Shared';
+import { share } from 'rxjs';
@Component({
@@ -15,8 +16,6 @@ import shared from '../../Shared';
})
export class ProfileComponent implements OnInit {
-
-
user: User = new User();
pictures: Picture[] = PICTURES;
@@ -90,18 +89,18 @@ export class ProfileComponent implements OnInit {
if (this.user.username != editedUser.username) { //promenio username, ide logout
this.user = editedUser;
this.resetInfo();
- alert("Nakon promene korisničkog imena, moraćete ponovo da se ulogujete.");
+ shared.openDialog("Obaveštenje", "Nakon promene korisničkog imena, moraćete ponovo da se ulogujete.");
this.authService.logOut();
this.router.navigate(['']);
return;
}
- alert("Podaci su uspešno promenjeni.");
+ shared.openDialog("Obaveštenje", "Podaci su uspešno promenjeni.");
this.user = editedUser;
console.log(this.user);
this.resetInfo();
}, (error: any) =>{
if (error.error == "Username already exists!") {
- alert("Ukucano korisničko ime je već zauzeto!\nIzaberite neko drugo.");
+ shared.openDialog("Obaveštenje", "Ukucano korisničko ime je već zauzeto! Izaberite neko drugo.");
//(<HTMLSelectElement>document.getElementById("inputUsername")).focus();
//poruka obavestenja ispod inputa
this.resetInfo();
@@ -131,7 +130,7 @@ export class ProfileComponent implements OnInit {
this.userInfoService.changeUserPassword(passwordArray).subscribe((response: any) => {
//console.log("PROMENIO LOZINKU");
this.resetNewPassInputs();
- alert("Nakon promene lozinke, moraćete ponovo da se ulogujete.");
+ shared.openDialog("Obaveštenje", "Nakon promene lozinke, moraćete ponovo da se ulogujete.");
this.authService.logOut();
this.router.navigate(['']);
}, (error: any) => {
@@ -142,7 +141,7 @@ export class ProfileComponent implements OnInit {
return;
}
else if (error.error == 'Identical password!') {
- alert("Stara i nova lozinka su identične.");
+ shared.openDialog("Obaveštenje", "Stara i nova lozinka su identične.");
this.resetNewPassInputs();
//(<HTMLSelectElement>document.getElementById("inputNewPassword")).focus();
return;
diff --git a/frontend/src/app/_services/predictors.service.ts b/frontend/src/app/_services/predictors.service.ts
index 54ae5694..844cd706 100644
--- a/frontend/src/app/_services/predictors.service.ts
+++ b/frontend/src/app/_services/predictors.service.ts
@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { API_SETTINGS } from 'src/config';
import Predictor from '../_data/Predictor';
+import { Column } from '../_pages/predict/predict.component';
import { AuthService } from './auth.service';
@Injectable({
@@ -21,7 +22,15 @@ export class PredictorsService {
return this.http.get<Predictor>(`${API_SETTINGS.apiURL}/predictor/getpredictor/`+ id, { headers: this.authService.authHeader() });
}
- usePredictor(predictor: Predictor, inputs : String[]) {
+ usePredictor(predictor: Predictor, inputs : Column[]) {
return this.http.post(`${API_SETTINGS.apiURL}/predictor/usepredictor/` + predictor._id, inputs, { headers: this.authService.authHeader() });
}
+
+ deletePredictor(predictor: Predictor) {
+ return this.http.delete(`${API_SETTINGS.apiURL}/predictor/` + predictor.name, { headers: this.authService.authHeader(), responseType: "text" });
+ }
+
+ getMyPredictors(): Observable<Predictor[]> {
+ return this.http.get<Predictor[]>(`${API_SETTINGS.apiURL}/predictor/mypredictors`, { headers: this.authService.authHeader() });
+ }
}
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index d90de54d..8098df40 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -1,4 +1,4 @@
-import { NgModule } from '@angular/core';
+import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
@@ -39,6 +39,7 @@ import { FilterDatasetsComponent } from './_pages/filter-datasets/filter-dataset
import { ReactiveBackgroundComponent } from './_elements/reactive-background/reactive-background.component';
import { ItemModelComponent } from './_elements/item-model/item-model.component';
import { AnnvisualComponent } from './_elements/annvisual/annvisual.component';
+import { AlertDialogComponent } from './_modals/alert-dialog/alert-dialog.component';
@NgModule({
declarations: [
@@ -67,7 +68,8 @@ import { AnnvisualComponent } from './_elements/annvisual/annvisual.component';
FilterDatasetsComponent,
ReactiveBackgroundComponent,
ItemModelComponent,
- AnnvisualComponent
+ AnnvisualComponent,
+ AlertDialogComponent
],
imports: [
BrowserModule,
@@ -84,6 +86,8 @@ import { AnnvisualComponent } from './_elements/annvisual/annvisual.component';
Ng2SearchPipeModule,
],
providers: [],
- bootstrap: [AppComponent]
+ bootstrap: [AppComponent],
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
+ entryComponents: [AlertDialogComponent]
})
export class AppModule { }
diff --git a/frontend/src/app/material.module.ts b/frontend/src/app/material.module.ts
index e85419ee..d16cef3d 100644
--- a/frontend/src/app/material.module.ts
+++ b/frontend/src/app/material.module.ts
@@ -1,18 +1,21 @@
import { NgModule } from '@angular/core';
-
+import { CommonModule } from '@angular/common';
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';
+import { MatIconModule } from '@angular/material/icon';
@NgModule({
exports: [
+ CommonModule,
MatDialogModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
- MatCheckboxModule
+ MatCheckboxModule,
+ MatIconModule
]
})
export class MaterialModule {} \ No newline at end of file