aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/api/api/Controllers/DatasetController.cs105
-rw-r--r--backend/api/api/Controllers/ExperimentController.cs56
-rw-r--r--backend/api/api/Controllers/FileController.cs83
-rw-r--r--backend/api/api/Controllers/ModelController.cs122
-rw-r--r--backend/api/api/Controllers/PredictorController.cs142
-rw-r--r--backend/api/api/Controllers/UserController.cs76
-rw-r--r--backend/api/api/Models/Dataset.cs1
-rw-r--r--backend/api/api/Models/Experiment.cs1
-rw-r--r--backend/api/api/Models/Model.cs1
-rw-r--r--backend/api/api/Models/Predictor.cs9
-rw-r--r--backend/api/api/Services/IPredictorService.cs1
-rw-r--r--backend/api/api/Services/PredictorService.cs14
-rw-r--r--backend/microservice/api/ml_service.py138
-rw-r--r--frontend/package-lock.json167
-rw-r--r--frontend/src/app/Shared.ts13
-rw-r--r--frontend/src/app/_data/Dataset.ts1
-rw-r--r--frontend/src/app/_data/Experiment.ts37
-rw-r--r--frontend/src/app/_data/Model.ts31
-rw-r--r--frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.html4
-rw-r--r--frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.ts86
-rw-r--r--frontend/src/app/_elements/dataset-load/dataset-load.component.html2
-rw-r--r--frontend/src/app/_elements/dataset-load/dataset-load.component.ts45
-rw-r--r--frontend/src/app/_elements/datatable/datatable.component.html70
-rw-r--r--frontend/src/app/_elements/datatable/datatable.component.ts18
-rw-r--r--frontend/src/app/_elements/item-dataset/item-dataset.component.css23
-rw-r--r--frontend/src/app/_elements/item-dataset/item-dataset.component.html53
-rw-r--r--frontend/src/app/_elements/item-dataset/item-dataset.component.ts27
-rw-r--r--frontend/src/app/_elements/item-experiment/item-experiment.component.css0
-rw-r--r--frontend/src/app/_elements/item-experiment/item-experiment.component.html10
-rw-r--r--frontend/src/app/_elements/item-experiment/item-experiment.component.spec.ts25
-rw-r--r--frontend/src/app/_elements/item-experiment/item-experiment.component.ts15
-rw-r--r--frontend/src/app/_elements/item-model/item-model.component.css23
-rw-r--r--frontend/src/app/_elements/item-model/item-model.component.html59
-rw-r--r--frontend/src/app/_elements/item-model/item-model.component.ts15
-rw-r--r--frontend/src/app/_elements/model-load/model-load.component.html49
-rw-r--r--frontend/src/app/_elements/model-load/model-load.component.ts5
-rw-r--r--frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.css0
-rw-r--r--frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.html8
-rw-r--r--frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.spec.ts25
-rw-r--r--frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.ts33
-rw-r--r--frontend/src/app/_pages/my-datasets/my-datasets.component.css8
-rw-r--r--frontend/src/app/_pages/my-datasets/my-datasets.component.html13
-rw-r--r--frontend/src/app/_pages/my-datasets/my-datasets.component.ts8
-rw-r--r--frontend/src/app/_pages/my-models/my-models.component.css12
-rw-r--r--frontend/src/app/_pages/my-models/my-models.component.html17
-rw-r--r--frontend/src/app/_pages/my-models/my-models.component.ts5
-rw-r--r--frontend/src/app/_pages/my-predictors/my-predictors.component.html2
-rw-r--r--frontend/src/app/_services/experiments.service.ts4
-rw-r--r--frontend/src/app/_services/models.service.ts4
-rw-r--r--frontend/src/app/app.module.ts4
-rw-r--r--frontend/src/app/experiment/experiment.component.html129
-rw-r--r--frontend/src/app/experiment/experiment.component.ts57
-rw-r--r--frontend/src/app/training/training.component.css2
-rw-r--r--frontend/src/app/training/training.component.html20
-rw-r--r--frontend/src/app/training/training.component.ts42
55 files changed, 1076 insertions, 844 deletions
diff --git a/backend/api/api/Controllers/DatasetController.cs b/backend/api/api/Controllers/DatasetController.cs
index 375b5bfd..add85aba 100644
--- a/backend/api/api/Controllers/DatasetController.cs
+++ b/backend/api/api/Controllers/DatasetController.cs
@@ -25,11 +25,7 @@ namespace api.Controllers
_fileService = fileService;
jwtToken = Token;
}
-
- // GET: api/<DatasetController>/mydatasets
- [HttpGet("mydatasets")]
- [Authorize(Roles = "User,Guest")]
- public ActionResult<List<Dataset>> Get()
+ public string getUsername()
{
string username;
var header = Request.Headers[HeaderNames.Authorization];
@@ -42,8 +38,21 @@ namespace api.Controllers
return null;
}
else
+ return null;
+
+ return username;
+ }
+
+ // GET: api/<DatasetController>/mydatasets
+ [HttpGet("mydatasets")]
+ [Authorize(Roles = "User,Guest")]
+ public ActionResult<List<Dataset>> Get()
+ {
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
- //U slucaju da je korisnik gost vrati dataSetove igrannonice
+
if (username == "")
return _datasetService.GetGuestDatasets();
@@ -60,22 +69,13 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult<List<Dataset>> SortDatasets(bool ascdsc, int latest)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
List<Dataset> lista = _datasetService.SortDatasets(username, ascdsc, latest);
-
if (latest == 0)
return lista;
else
@@ -100,17 +100,9 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult<List<Dataset>> Search(string name)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
//ako bude trebao ID, samo iz baze uzeti
@@ -125,17 +117,9 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult<Dataset> Get(string name)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
var dataset = _datasetService.GetOneDataset(username, name);
@@ -145,18 +129,6 @@ namespace api.Controllers
return dataset;
}
- /*za pretragu vratiti dataset koji je public
- public ActionResult<Dataset> Get(string name)
- {
- var dataset = _datasetService.GetOneDataset(username, name);
-
- if (dataset == null)
- return NotFound($"Dataset with name = {name} or user with username = {username} not found");
-
- return dataset;
- }
- */
-
// POST api/<DatasetController>/add
[HttpPost("add")]
[Authorize(Roles = "User,Guest")]
@@ -183,7 +155,6 @@ namespace api.Controllers
return NotFound($"Dateset with name = {dataset.name} exisits");
else
{
-
FileModel fileModel = _fileService.getFile(dataset.fileId);
dataset.isPreProcess = false;
_datasetService.Create(dataset);
@@ -198,17 +169,9 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult Put(string name, [FromBody] Dataset dataset)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
var existingDataset = _datasetService.GetOneDataset(username, name);
@@ -229,17 +192,9 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult Delete(string name)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
var dataset = _datasetService.GetOneDataset(username, name);
diff --git a/backend/api/api/Controllers/ExperimentController.cs b/backend/api/api/Controllers/ExperimentController.cs
index 0063c532..3fa02943 100644
--- a/backend/api/api/Controllers/ExperimentController.cs
+++ b/backend/api/api/Controllers/ExperimentController.cs
@@ -25,10 +25,7 @@ namespace api.Controllers
_mlConnectionService = mlConnectionService;
_fileService = fileService;
}
-
- [HttpPost("add")]
- [Authorize(Roles = "User,Guest")]
- public async Task<ActionResult<Experiment>> Post([FromBody] Experiment experiment)
+ public string getUserId()
{
string uploaderId;
var header = Request.Headers[HeaderNames.Authorization];
@@ -38,15 +35,27 @@ namespace api.Controllers
var parameter = headerValue.Parameter;
uploaderId = jwtToken.TokenToId(parameter);
if (uploaderId == null)
- return BadRequest();
+ return null;
}
else
+ return null;
+
+ return uploaderId;
+ }
+
+ [HttpPost("add")]
+ [Authorize(Roles = "User,Guest")]
+ public async Task<ActionResult<Experiment>> Post([FromBody] Experiment experiment)
+ {
+ string uploaderId = getUserId();
+
+ if (uploaderId == null)
return BadRequest();
experiment.uploaderId = uploaderId;
var existingExperiment = _experimentService.Get(uploaderId, experiment.name);
if(existingExperiment != null)
- return NotFound($"Experiment with name = {experiment.name} exisits");
+ return NotFound($"Experiment with this name exists");
_experimentService.Create(experiment);
return Ok(experiment);
}
@@ -55,17 +64,9 @@ namespace api.Controllers
[Authorize(Roles = "User,Guest")]
public async Task<ActionResult<Experiment>> Get(string id)
{
- string uploaderId;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- uploaderId = jwtToken.TokenToId(parameter);
- if (uploaderId == null)
- return null;
- }
- else
+ string uploaderId = getUserId();
+
+ if (uploaderId == null)
return BadRequest();
var experiment = _experimentService.Get(id);
@@ -75,28 +76,17 @@ namespace api.Controllers
return Ok(experiment);
}
- [HttpPost("getMyExperiments")]
+ [HttpGet("getMyExperiments")]
[Authorize(Roles = "User,Guest")]
public async Task<ActionResult<List<Experiment>>> getMyExperiments()
{
- string uploaderId;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- uploaderId = jwtToken.TokenToId(parameter);
- if (uploaderId == null)
- return null;
- }
- else
+ string uploaderId = getUserId();
+
+ if (uploaderId == null)
return BadRequest();
+
var experiments=_experimentService.GetMyExperiments(uploaderId);
return Ok(experiments);
-
}
-
-
-
}
}
diff --git a/backend/api/api/Controllers/FileController.cs b/backend/api/api/Controllers/FileController.cs
index 0be480f2..b9b31500 100644
--- a/backend/api/api/Controllers/FileController.cs
+++ b/backend/api/api/Controllers/FileController.cs
@@ -25,18 +25,12 @@ namespace api.Controllers
_fileservice = fileService;
}
- [HttpPost("h5")]
- [Authorize(Roles = "User,Guest")]
- public async Task<ActionResult<string>> H5Upload([FromForm] IFormFile file)
+ public string getUserId()
{
-
- //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);
@@ -44,7 +38,25 @@ namespace api.Controllers
return null;
}
else
+ return null;
+
+ return uploaderId;
+ }
+
+ [HttpPost("h5")]
+ [Authorize(Roles = "User,Guest")]
+ public async Task<ActionResult<string>> H5Upload([FromForm] IFormFile file)
+ {
+
+ //get username from jwtToken
+
+ string folderName;
+
+ string uploaderId = getUserId();
+
+ if (uploaderId == null)
return BadRequest();
+
if (uploaderId == "")
{
folderName = "TempFiles";
@@ -101,18 +113,9 @@ namespace api.Controllers
public ActionResult<string> CsvRead(bool hasHeader, string fileId)
{
- string uploaderId;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
+ string uploaderId = getUserId();
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- uploaderId = _token.TokenToId(parameter);
- if (uploaderId == null)
- return null;
- }
- else
+ if (uploaderId == null)
return BadRequest();
//String csvContent = System.IO.File.ReadAllText(fileModel.path);
@@ -121,9 +124,9 @@ namespace api.Controllers
if (hasHeader)
- return String.Join("", System.IO.File.ReadLines(filePath).Take(11));
+ return String.Join("\n", System.IO.File.ReadLines(filePath).Take(11));
else
- return String.Join("", System.IO.File.ReadLines(filePath).Take(10));
+ return String.Join("\n", System.IO.File.ReadLines(filePath).Take(10));
}
@@ -135,18 +138,12 @@ namespace api.Controllers
{
//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
+ string uploaderId = getUserId();
+
+ if (uploaderId == null)
return BadRequest();
if (uploaderId == "")
@@ -215,18 +212,9 @@ namespace api.Controllers
public async Task<ActionResult> DownloadH5(string id)
{
//Get Username
- string uploaderId;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
+ string uploaderId = getUserId();
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- uploaderId = _token.TokenToId(parameter);
- if (uploaderId == null)
- return null;
- }
- else
+ if (uploaderId == null)
return BadRequest();
string filePath = _fileservice.GetFilePath(id, uploaderId);
@@ -242,18 +230,9 @@ namespace api.Controllers
public async Task<ActionResult> DownloadFile(string id)
{
//Get Username
- string uploaderId;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
+ string uploaderId = getUserId();
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- uploaderId = _token.TokenToId(parameter);
- if (uploaderId == null)
- return null;
- }
- else
+ if (uploaderId == null)
return BadRequest();
string filePath = _fileservice.GetFilePath(id, uploaderId);
diff --git a/backend/api/api/Controllers/ModelController.cs b/backend/api/api/Controllers/ModelController.cs
index 618b15e8..29911e07 100644
--- a/backend/api/api/Controllers/ModelController.cs
+++ b/backend/api/api/Controllers/ModelController.cs
@@ -33,9 +33,7 @@ namespace api.Controllers
_mlConnectionService = mlConnectionService;
}
- [HttpPost("sendModel")]
- [Authorize(Roles = "User,Guest")]
- public async Task<ActionResult<string>> Test([FromBody] string modelId,string experimentId)
+ public string getUserId()
{
string uploaderId;
var header = Request.Headers[HeaderNames.Authorization];
@@ -45,10 +43,43 @@ namespace api.Controllers
var parameter = headerValue.Parameter;
uploaderId = jwtToken.TokenToId(parameter);
if (uploaderId == null)
- return BadRequest();
+ return null;
}
else
+ return null;
+
+ return uploaderId;
+ }
+ public string getUsername()
+ {
+ string username;
+ var header = Request.Headers[HeaderNames.Authorization];
+ if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
+ {
+ var scheme = headerValue.Scheme;
+ var parameter = headerValue.Parameter;
+ username = jwtToken.TokenToUsername(parameter);
+ if (username == null)
+ return null;
+ }
+ else
+ return null;
+
+ return username;
+ }
+
+ [HttpPost("trainModel")]
+ [Authorize(Roles = "User,Guest")]
+ public async Task<ActionResult<string>> Test([FromBody] TrainModelObject trainModelObject)
+ {
+ string experimentId = trainModelObject.ExperimentId;
+ string modelId = trainModelObject.ModelId;
+
+ string uploaderId = getUserId();
+
+ if (uploaderId == null)
return BadRequest();
+
var experiment=_experimentService.Get(experimentId);
var dataset = _datasetService.GetOneDataset(experiment.datasetId);
var filepath = _fileService.GetFilePath(dataset.fileId, uploaderId);
@@ -62,17 +93,9 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult<List<Model>> Get()
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
return _modelService.GetMyModels(username);
@@ -84,17 +107,9 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult<Model> Get(string name)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
var model = _modelService.GetOneModel(username, name);
@@ -116,17 +131,9 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult<List<Model>> GetLatestModels(int latest)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
//ako bude trebao ID, samo iz baze uzeti
@@ -142,8 +149,6 @@ namespace api.Controllers
}
-
-
// POST api/<ModelController>/add
[HttpPost("add")]
[Authorize(Roles = "User,Guest")]
@@ -176,26 +181,14 @@ namespace api.Controllers
}
}
-
-
-
-
// PUT api/<ModelController>/{name}
[HttpPut("{name}")]
[Authorize(Roles = "User")]
public ActionResult Put(string name, [FromBody] Model model)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
@@ -213,17 +206,9 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult Delete(string name)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
var model = _modelService.GetOneModel(username, name);
@@ -238,4 +223,11 @@ namespace api.Controllers
}
}
+
+ public class TrainModelObject
+ {
+ public string ModelId { get; set; }
+ public string ExperimentId { get; set; }
+
+ }
}
diff --git a/backend/api/api/Controllers/PredictorController.cs b/backend/api/api/Controllers/PredictorController.cs
index b9215822..233ea401 100644
--- a/backend/api/api/Controllers/PredictorController.cs
+++ b/backend/api/api/Controllers/PredictorController.cs
@@ -1,7 +1,6 @@
using api.Models;
using api.Services;
using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Net.Http.Headers;
using System.Net.Http.Headers;
@@ -22,13 +21,9 @@ namespace api.Controllers
_predictorService = predictorService;
jwtToken = Token;
_mlConnectionService = mlConnectionService;
-
}
- // GET: api/<PredictorController>/mypredictors
- [HttpGet("mypredictors")]
- [Authorize(Roles = "User")]
- public ActionResult<List<Predictor>> Get()
+ public string getUsername()
{
string username;
var header = Request.Headers[HeaderNames.Authorization];
@@ -41,10 +36,24 @@ namespace api.Controllers
return null;
}
else
+ return null;
+
+ return username;
+ }
+
+ // GET: api/<PredictorController>/mypredictors
+ [HttpGet("mypredictors")]
+ [Authorize(Roles = "User")]
+ public ActionResult<List<Predictor>> Get()
+ {
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
return _predictorService.GetMyPredictors(username);
}
+
// GET: api/<PredictorController>/publicpredictors
[HttpGet("publicpredictors")]
public ActionResult<List<Predictor>> GetPublicPredictors()
@@ -52,29 +61,17 @@ namespace api.Controllers
return _predictorService.GetPublicPredictors();
}
-
-
//SEARCH za predictore (public ili private sa ovim imenom )
// GET api/<PredictorController>/search/{name}
[HttpGet("search/{name}")]
[Authorize(Roles = "User")]
public ActionResult<List<Predictor>> Search(string name)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
- //ako bude trebao ID, samo iz baze uzeti
-
return _predictorService.SearchPredictors(name, username);
}
@@ -83,20 +80,10 @@ namespace api.Controllers
[Authorize(Roles = "User,Guest")]
public ActionResult<Predictor> GetPredictor(string id)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
- return BadRequest();
+ string username = getUsername();
- //ako bude trebao ID, samo iz baze uzeti
+ if (username == null)
+ return BadRequest();
Predictor predictor = _predictorService.GetPredictor(username, id);
@@ -106,24 +93,14 @@ namespace api.Controllers
return predictor;
}
-
- //da li da se odvoji search za public i posebno za private?
// GET api/<PredictorController>/{name}
[HttpGet("{name}")]
[Authorize(Roles = "User")]
public ActionResult<Predictor> Get(string name)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
var predictor = _predictorService.GetOnePredictor(username, name);
@@ -143,20 +120,10 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult<List<Predictor>> SortPredictors(bool ascdsc, int latest)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
- return BadRequest();
+ string username = getUsername();
- //ako bude trebao ID, samo iz baze uzeti
+ if (username == null)
+ return BadRequest();
List<Predictor> lista = _predictorService.SortPredictors(username, ascdsc, latest);
@@ -172,6 +139,7 @@ namespace api.Controllers
return novaLista;
}
}
+
// POST api/<PredictorController>/add
[HttpPost("add")]
[Authorize(Roles = "User")]
@@ -194,18 +162,9 @@ namespace api.Controllers
[Authorize(Roles = "User,Guest")]
public ActionResult UsePredictor(String id, [FromBody] PredictorColumns[] inputs)
{
+ string username = getUsername();
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ if (username == null)
return BadRequest();
Predictor predictor = _predictorService.GetPredictor(username, id);
@@ -215,23 +174,14 @@ namespace api.Controllers
return NoContent();
}
-
// PUT api/<PredictorController>/{name}
[HttpPut("{name}")]
[Authorize(Roles = "User")]
public ActionResult Put(string name, [FromBody] Predictor predictor)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
var existingPredictor = _predictorService.GetOnePredictor(username, name);
@@ -245,30 +195,14 @@ namespace api.Controllers
return Ok($"Predictor with name = {name} updated");
}
- // odraditi pretragu predictora
- //potrebna public i private pretraga
- //prvo da napakuje svoje pa onda ostale
- //
- //isto odraditi i za datasetove
- //
-
-
// DELETE api/<PredictorController>/name
[HttpDelete("{name}")]
[Authorize(Roles = "User")]
public ActionResult Delete(string name)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
var predictor = _predictorService.GetOnePredictor(username, name);
@@ -281,9 +215,5 @@ namespace api.Controllers
return Ok($"Predictor with name = {name} deleted");
}
-
-
-
-
}
}
diff --git a/backend/api/api/Controllers/UserController.cs b/backend/api/api/Controllers/UserController.cs
index 782a02cf..9f736679 100644
--- a/backend/api/api/Controllers/UserController.cs
+++ b/backend/api/api/Controllers/UserController.cs
@@ -22,6 +22,23 @@ namespace api.Controllers
this.userService = userService;
jwtToken = token;
}
+ public string getUsername()
+ {
+ string username;
+ var header = Request.Headers[HeaderNames.Authorization];
+ if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
+ {
+ var scheme = headerValue.Scheme;
+ var parameter = headerValue.Parameter;
+ username = jwtToken.TokenToUsername(parameter);
+ if (username == null)
+ return null;
+ }
+ else
+ return null;
+
+ return username;
+ }
// GET: api/<UserController>
[HttpGet]
@@ -36,17 +53,9 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult<User> MyProfilePage()
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
var user = userService.GetUserUsername(username);
@@ -61,7 +70,6 @@ namespace api.Controllers
[HttpPost]
public ActionResult<User> Post([FromBody] User user)
{
-
var existingUser = userService.GetUserUsername(user.Username);
if (existingUser != null)
@@ -81,20 +89,10 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult PutPass([FromBody] string[] Password)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
- return BadRequest();
-
+ string username = getUsername();
+ if (username == null)
+ return BadRequest();
User user = new User();
@@ -122,17 +120,9 @@ namespace api.Controllers
[HttpPut("changeinfo")]
public ActionResult Put([FromBody] User user)
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
return Ok(userService.Update(username, user));
@@ -143,17 +133,9 @@ namespace api.Controllers
[Authorize(Roles = "User")]
public ActionResult Delete()
{
- string username;
- var header = Request.Headers[HeaderNames.Authorization];
- if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
- {
- var scheme = headerValue.Scheme;
- var parameter = headerValue.Parameter;
- username = jwtToken.TokenToUsername(parameter);
- if (username == null)
- return null;
- }
- else
+ string username = getUsername();
+
+ if (username == null)
return BadRequest();
var user = userService.GetUserUsername(username);
diff --git a/backend/api/api/Models/Dataset.cs b/backend/api/api/Models/Dataset.cs
index 12dcfa08..47814449 100644
--- a/backend/api/api/Models/Dataset.cs
+++ b/backend/api/api/Models/Dataset.cs
@@ -25,6 +25,7 @@ namespace api.Models
public bool hasHeader { get; set; }
public ColumnInfo[] columnInfo { get; set; }
+ public int rowCount { get; set; }
public int nullCols { get; set; }
public int nullRows { get; set; }
public bool isPreProcess { get; set; }
diff --git a/backend/api/api/Models/Experiment.cs b/backend/api/api/Models/Experiment.cs
index d5ce7627..bf029116 100644
--- a/backend/api/api/Models/Experiment.cs
+++ b/backend/api/api/Models/Experiment.cs
@@ -10,6 +10,7 @@ namespace api.Models
public string _id { get; set; }
public string name { get; set; }
public string description { get; set; }
+ public string encoding { get; set; }
public List<string> ModelIds { get; set; }
public string datasetId { get; set; }
public string uploaderId { get; set; }
diff --git a/backend/api/api/Models/Model.cs b/backend/api/api/Models/Model.cs
index f0e4d346..72f989a6 100644
--- a/backend/api/api/Models/Model.cs
+++ b/backend/api/api/Models/Model.cs
@@ -23,7 +23,6 @@ namespace api.Models
//Neural net training
public string type { get; set; }
- public string encoding { get; set; }
public string optimizer { get; set; }
public string lossFunction { get; set; }
//public int inputNeurons { get; set; }
diff --git a/backend/api/api/Models/Predictor.cs b/backend/api/api/Models/Predictor.cs
index 911a9aee..b1d6444b 100644
--- a/backend/api/api/Models/Predictor.cs
+++ b/backend/api/api/Models/Predictor.cs
@@ -24,7 +24,7 @@ namespace api.Models
/*
{
- "_id" : "6244950f26cf2385bc29ba28",
+ "_id" : "",
"username" : "ivan123",
"name" : "Neki prediktor",
"description" : "Neki opis prediktora koji je unet tamo",
@@ -32,9 +32,10 @@ namespace api.Models
"proba2",
"proba3"
],
- "output" : "",
+ "output" : "izlaz",
"isPublic" : true,
- "accessibleByLink" : false,
- "dateCreated" : "232"
+ "accessibleByLink" : true,
+ "dateCreated" : "2022-04-11T20:33:26.937+00:00",
+ "experimentId" : "Neki id eksperimenta"
}
*/ \ No newline at end of file
diff --git a/backend/api/api/Services/IPredictorService.cs b/backend/api/api/Services/IPredictorService.cs
index 7ea8d85e..729dd0b6 100644
--- a/backend/api/api/Services/IPredictorService.cs
+++ b/backend/api/api/Services/IPredictorService.cs
@@ -14,7 +14,6 @@ namespace api.Services
Predictor Create(Predictor predictor);
void Update(string username, string name, Predictor predictor);
void Delete(string username, string name);
- bool CheckDb();
}
}
diff --git a/backend/api/api/Services/PredictorService.cs b/backend/api/api/Services/PredictorService.cs
index 22432ec2..b89eaded 100644
--- a/backend/api/api/Services/PredictorService.cs
+++ b/backend/api/api/Services/PredictorService.cs
@@ -45,12 +45,11 @@ namespace api.Services
return _predictor.Find(predictor => predictor._id == id && (predictor.username == username || predictor.isPublic == true)).FirstOrDefault();
}
- //last private models
+
public List<Predictor> SortPredictors(string username, bool ascdsc, int latest)
{
List<Predictor> list = _predictor.Find(predictor => predictor.username == username).ToList();
-
if (ascdsc)
list = list.OrderBy(predictor => predictor.dateCreated).ToList();
else
@@ -66,17 +65,6 @@ namespace api.Services
public void Update(string username, string name, Predictor predictor)
{
_predictor.ReplaceOne(predictor => predictor.username == username && predictor.name == name, predictor);
-
- }
- public bool CheckDb()
- {
- Predictor? predictor = null;
- predictor = _predictor.Find(predictor => predictor.username == "igrannonica").FirstOrDefault();
-
- if (predictor != null)
- return false;
- else
- return true;
}
}
}
diff --git a/backend/microservice/api/ml_service.py b/backend/microservice/api/ml_service.py
index b5f5e9bf..4d2212f7 100644
--- a/backend/microservice/api/ml_service.py
+++ b/backend/microservice/api/ml_service.py
@@ -101,99 +101,103 @@ class TrainingResultRegression:
class TrainingResult:
metrics: dict
'''
-def train(dataset, params, callback):
- problem_type = params["type"]
- data = pd.DataFrame()
- for col in params["inputColumns"]:
- data[col]=dataset[col]
+def train(dataset, paramsModel, paramsExperiment, callback):
+ problem_type = paramsModel["type"]
+ dataModel = pd.DataFrame()
+ dataExperiment = pd.DataFrame()
+ for col in paramsModel["inputColumns"]:
+ dataModel[col]=dataset[col]
+ for col in paramsExperiment["inputColumns"]:
+ dataExperiment[col]=dataset[col]
- print(data.head())
- output_column = params["columnToPredict"]
- data[output_column] = dataset[output_column]
+ print(dataModel.head())
+ output_column_model = paramsModel["columnToPredict"]
+ output_column_experiment = paramsExperiment["outputColumn"]
+ dataModel[output_column_model] = dataset[output_column_model]
#
# Brisanje null kolona / redova / zamena
#nullreplace=[
# {"column":"Embarked","value":"C","deleteRow":false,"deleteCol":true},
# {"column": "Cabin","value":"C123","deleteRow":"0","deleteCol":"0"}]
- null_value_options = params["nullValues"]
- null_values_replacers = params["nullValuesReplacers"]
+ null_value_options = paramsModel["nullValues"]
+ null_values_replacers = paramsModel["nullValuesReplacers"]
if(null_value_options=='replace'):
print("replace null") # TODO
elif(null_value_options=='delete_rows'):
- data=data.dropna()
+ dataModel=dataModel.dropna()
elif(null_value_options=='delete_columns'):
- data=data.dropna()
+ dataModel=dataModel.dropna()
#
#print(data.isnull().any())
#
# Brisanje kolona koje ne uticu na rezultat
#
- num_rows=data.shape[0]
- for col in data.columns:
- if((data[col].nunique()==(num_rows)) and (data[col].dtype==np.object_)):
- data.pop(col)
+ num_rows=dataModel.shape[0]
+ for col in dataModel.columns:
+ if((dataModel[col].nunique()==(num_rows)) and (dataModel[col].dtype==np.object_)):
+ dataModel.pop(col)
#
# Enkodiranje
# https://www.analyticsvidhya.com/blog/2020/08/types-of-categorical-data-encoding/
#
- encoding=params["encoding"]
+ encoding=paramsModel["encoding"]
if(encoding=='label'):
encoder=LabelEncoder()
- for col in data.columns:
- if(data[col].dtype==np.object_):
- data[col]=encoder.fit_transform(data[col])
+ for col in dataModel.columns:
+ if(dataModel[col].dtype==np.object_):
+ dataModel[col]=encoder.fit_transform(dataModel[col])
elif(encoding=='onehot'):
category_columns=[]
- for col in data.columns:
- if(data[col].dtype==np.object_):
+ for col in dataModel.columns:
+ if(dataModel[col].dtype==np.object_):
category_columns.append(col)
- data=pd.get_dummies(data, columns=category_columns, prefix=category_columns)
+ dataModel=pd.get_dummies(dataModel, columns=category_columns, prefix=category_columns)
elif(encoding=='ordinal'):
encoder = OrdinalEncoder()
- for col in data.columns:
- if(data[col].dtype==np.object_):
- data[col]=encoder.fit_transform(data[col])
+ for col in dataModel.columns:
+ if(dataModel[col].dtype==np.object_):
+ dataModel[col]=encoder.fit_transform(dataModel[col])
elif(encoding=='hashing'):
category_columns=[]
- for col in data.columns:
- if(data[col].dtype==np.object_):
+ for col in dataModel.columns:
+ if(dataModel[col].dtype==np.object_):
category_columns.append(col)
encoder=ce.HashingEncoder(cols=category_columns, n_components=len(category_columns))
- encoder.fit_transform(data)
+ encoder.fit_transform(dataModel)
elif(encoding=='binary'):
category_columns=[]
- for col in data.columns:
- if(data[col].dtype==np.object_):
+ for col in dataModel.columns:
+ if(dataModel[col].dtype==np.object_):
category_columns.append(col)
encoder=ce.BinaryEncoder(cols=category_columns, return_df=True)
- encoder.fit_transform(data)
+ encoder.fit_transform(dataModel)
elif(encoding=='baseN'):
category_columns=[]
- for col in data.columns:
- if(data[col].dtype==np.object_):
+ for col in dataModel.columns:
+ if(dataModel[col].dtype==np.object_):
category_columns.append(col)
encoder=ce.BaseNEncoder(cols=category_columns, return_df=True, base=5)
- encoder.fit_transform(data)
+ encoder.fit_transform(dataModel)
#
# Input - output
#
x_columns = []
- for col in data.columns:
- if(col!=output_column):
+ for col in dataModel.columns:
+ if(col!=output_column_model):
x_columns.append(col)
- x = data[x_columns].values
- y = data[output_column].values
+ x = dataModel[x_columns].values
+ y = dataModel[output_column_model].values
print(x_columns)
print(x)
#
# Podela na test i trening skupove
#
- test=params["randomTestSetDistribution"]
- randomOrder = params["randomOrder"]
+ test=paramsModel["randomTestSetDistribution"]
+ randomOrder = paramsModel["randomOrder"]
if(randomOrder):
random=123
else:
@@ -213,60 +217,60 @@ def train(dataset, params, callback):
# Treniranje modela
#
#
- hidden_layer_neurons = params["hiddenLayerNeurons"]
+ hidden_layer_neurons = paramsModel["hiddenLayerNeurons"]
if(problem_type=='multi-klasifikacioni'):
- func=params['hiddenLayerActivationFunctions']
- output_func = params["outputLayerActivationFunction"]
- optimizer = params["optimizer"]
- metrics=params['metrics']
- loss_func=params["lossFunction"]
- batch_size = params["batchSize"]
- epochs = params["epochs"]
- inputDim = len(data.columns) - 1
+ func=paramsModel['hiddenLayerActivationFunctions']
+ output_func = paramsModel["outputLayerActivationFunction"]
+ optimizer = paramsModel["optimizer"]
+ metrics=paramsModel['metrics']
+ loss_func=paramsModel["lossFunction"]
+ batch_size=paramsModel["batchSize"]
+ epochs=paramsModel["epochs"]
+ inputDim=len(dataModel.columns) - 1
'''
classifier=tf.keras.Sequential()
- classifier.add(tf.keras.layers.Dense(units=len(data.columns),input_dim=inputDim))#input layer
+ classifier.add(tf.keras.layers.Dense(units=len(dataModel.columns),input_dim=inputDim))#input layer
for f in func:#hidden layers
classifier.add(tf.keras.layers.Dense(hidden_layer_neurons,activation=f))
- numberofclasses=len(output_column.unique())
+ numberofclasses=len(output_column_model.unique())
classifier.add(tf.keras.layers.Dense(numberofclasses,activation=output_func))#output layer
'''
model=tf.keras.Sequential()
model.add(tf.keras.layers.Dense(1,input_dim=x_train.shape[1]))#input layer
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
- model.add(tf.keras.layers.Dense(len(output_column.unique())+1, activation='softmax'))
+ model.add(tf.keras.layers.Dense(len(output_column_model.unique())+1, activation='softmax'))
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()
- for func in params["hiddenLayerActivationFunctions"]:
- layers = params["hiddenLayers"]
- for numNeurons in params["hiddenLayerNeurons"]:
+ for func in paramsModel["hiddenLayerActivationFunctions"]:
+ layers = paramsModel["hiddenLayers"]
+ for numNeurons in paramsModel["hiddenLayerNeurons"]:
classifier.add(tf.keras.layers.Dense(units=numNeurons,activation=func))
- output_func = params["outputLayerActivationFunction"]
+ output_func = paramsModel["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"]
+ optimizer = paramsModel["optimizer"]
+ metrics=paramsModel['metrics']
+ loss_func=paramsModel["lossFunction"]
classifier.compile(optimizer=optimizer, loss=loss_func,metrics=metrics)
- batch_size = params["batchSize"]
- epochs = params["epochs"]
+ batch_size = paramsModel["batchSize"]
+ epochs = paramsModel["epochs"]
history=classifier.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, callbacks=callback(x_test, y_test), validation_split=0.2) # TODO params["validationSplit"]
#
# Test
#
- model_name = params['_id']
+ model_name = paramsModel['_id']
#y_pred=classifier.predict(x_test)
if(problem_type == "regresioni"):
y_pred=classifier.predict(x_test)
@@ -375,8 +379,8 @@ def manageH5(datain,params,h5model):
data = pd.DataFrame()
for col in params["inputColumns"]:
data[col]=dataset[col]
- output_column = params["columnToPredict"]
- data[output_column] = dataset[output_column]
+ output_column_model = params["columnToPredict"]
+ data[output_column_model] = dataset[output_column_model]
#
# Brisanje null kolona / redova / zamena
#nullreplace=[
@@ -450,10 +454,10 @@ def manageH5(datain,params,h5model):
#
x_columns = []
for col in data.columns:
- if(col!=output_column):
+ if(col!=output_column_model):
x_columns.append(col)
x = data[x_columns].values
- y = data[output_column].values
+ y = data[output_column_model].values
y_pred=h5model.predict_classes(x) \ No newline at end of file
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index a82131d5..20a636e3 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -453,6 +453,7 @@
"version": "13.2.5",
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-13.2.5.tgz",
"integrity": "sha512-Xd8xj2Z0ilA4TJAM/JkTtA1CAa6SuebFsEEvabHCRO5MDvtdsIUP91ADUZIqDHy7qe6Qift/rAVN2PXxT2aaNA==",
+ "dev": true,
"dependencies": {
"@babel/core": "^7.17.2",
"chokidar": "^3.0.0",
@@ -482,6 +483,7 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz",
"integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==",
+ "dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.0"
},
@@ -493,6 +495,7 @@
"version": "7.17.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz",
"integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==",
+ "dev": true,
"dependencies": {
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.16.7",
@@ -522,6 +525,7 @@
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
"bin": {
"semver": "bin/semver.js"
}
@@ -530,6 +534,7 @@
"version": "7.17.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz",
"integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==",
+ "dev": true,
"dependencies": {
"@babel/types": "^7.17.0",
"jsesc": "^2.5.1",
@@ -543,6 +548,7 @@
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -782,6 +788,7 @@
"version": "7.16.12",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz",
"integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==",
+ "dev": true,
"dependencies": {
"@babel/code-frame": "^7.16.7",
"@babel/generator": "^7.16.8",
@@ -811,6 +818,7 @@
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
"bin": {
"semver": "bin/semver.js"
}
@@ -819,6 +827,7 @@
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -827,6 +836,7 @@
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz",
"integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==",
+ "dev": true,
"dependencies": {
"@babel/types": "^7.16.8",
"jsesc": "^2.5.1",
@@ -840,6 +850,7 @@
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3366,6 +3377,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -3639,6 +3651,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true,
"engines": {
"node": ">=8"
}
@@ -3735,6 +3748,7 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
@@ -3912,6 +3926,7 @@
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
"funding": [
{
"type": "individual",
@@ -4930,6 +4945,7 @@
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz",
"integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==",
+ "dev": true,
"engines": {
"node": ">= 0.6.0"
}
@@ -5906,6 +5922,7 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -6074,6 +6091,7 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -6183,6 +6201,7 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
@@ -6775,6 +6794,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
"dependencies": {
"binary-extensions": "^2.0.0"
},
@@ -6828,6 +6848,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -6844,6 +6865,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
@@ -6870,6 +6892,7 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
"engines": {
"node": ">=0.12.0"
}
@@ -7735,6 +7758,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
"dependencies": {
"yallist": "^4.0.0"
},
@@ -7746,6 +7770,7 @@
"version": "0.25.7",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
+ "dev": true,
"dependencies": {
"sourcemap-codec": "^1.4.4"
}
@@ -8387,6 +8412,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -9082,6 +9108,7 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
"engines": {
"node": ">=8.6"
},
@@ -9896,6 +9923,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
"dependencies": {
"picomatch": "^2.2.1"
},
@@ -9906,7 +9934,8 @@
"node_modules/reflect-metadata": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
- "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
+ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
+ "dev": true
},
"node_modules/regenerate": {
"version": "1.4.2",
@@ -10326,6 +10355,7 @@
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -10710,7 +10740,8 @@
"node_modules/sourcemap-codec": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
- "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+ "dev": true
},
"node_modules/spdy": {
"version": "4.0.2",
@@ -11111,6 +11142,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
@@ -11202,6 +11234,7 @@
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
"integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
+ "dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -11841,7 +11874,8 @@
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
},
"node_modules/yaml": {
"version": "1.10.2",
@@ -12176,6 +12210,7 @@
"version": "13.2.5",
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-13.2.5.tgz",
"integrity": "sha512-Xd8xj2Z0ilA4TJAM/JkTtA1CAa6SuebFsEEvabHCRO5MDvtdsIUP91ADUZIqDHy7qe6Qift/rAVN2PXxT2aaNA==",
+ "dev": true,
"requires": {
"@babel/core": "^7.17.2",
"chokidar": "^3.0.0",
@@ -12193,6 +12228,7 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz",
"integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==",
+ "dev": true,
"requires": {
"@jridgewell/trace-mapping": "^0.3.0"
}
@@ -12201,6 +12237,7 @@
"version": "7.17.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz",
"integrity": "sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==",
+ "dev": true,
"requires": {
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.16.7",
@@ -12222,7 +12259,8 @@
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
}
}
},
@@ -12230,6 +12268,7 @@
"version": "7.17.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz",
"integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==",
+ "dev": true,
"requires": {
"@babel/types": "^7.17.0",
"jsesc": "^2.5.1",
@@ -12239,7 +12278,8 @@
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
}
}
},
@@ -12384,6 +12424,7 @@
"version": "7.16.12",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz",
"integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==",
+ "dev": true,
"requires": {
"@babel/code-frame": "^7.16.7",
"@babel/generator": "^7.16.8",
@@ -12405,12 +12446,14 @@
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
}
}
},
@@ -12418,6 +12461,7 @@
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz",
"integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==",
+ "dev": true,
"requires": {
"@babel/types": "^7.16.8",
"jsesc": "^2.5.1",
@@ -12427,7 +12471,8 @@
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
}
}
},
@@ -13605,8 +13650,7 @@
"version": "13.2.5",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-13.2.5.tgz",
"integrity": "sha512-obiPvwPe+UJUO8cfNbBxukLKG30F+gLF5/erexwklRknJzS4KP8ciH2on6XlTuXUahpDjbO0pffugFE2I/IszQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"@nodelib/fs.scandir": {
"version": "2.1.5",
@@ -14206,8 +14250,7 @@
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
"integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"adjust-sourcemap-loader": {
"version": "4.0.0",
@@ -14330,6 +14373,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dev": true,
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -14527,7 +14571,8 @@
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
- "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "dev": true
},
"bl": {
"version": "4.1.0",
@@ -14598,8 +14643,7 @@
"bootstrap": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz",
- "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==",
- "requires": {}
+ "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q=="
},
"brace-expansion": {
"version": "1.1.11",
@@ -14614,6 +14658,7 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
"requires": {
"fill-range": "^7.0.1"
}
@@ -14742,6 +14787,7 @@
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "dev": true,
"requires": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
@@ -14769,8 +14815,7 @@
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.2.tgz",
"integrity": "sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"clean-stack": {
"version": "2.2.0",
@@ -15248,8 +15293,7 @@
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz",
"integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"css-select": {
"version": "4.2.1",
@@ -15515,7 +15559,8 @@
"dependency-graph": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz",
- "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg=="
+ "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==",
+ "dev": true
},
"destroy": {
"version": "1.0.4",
@@ -16182,6 +16227,7 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
"requires": {
"to-regex-range": "^5.0.1"
}
@@ -16304,6 +16350,7 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
"optional": true
},
"function-bind": {
@@ -16379,6 +16426,7 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
"requires": {
"is-glob": "^4.0.1"
}
@@ -16635,8 +16683,7 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"ieee754": {
"version": "1.2.1",
@@ -16833,6 +16880,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
"requires": {
"binary-extensions": "^2.0.0"
}
@@ -16864,7 +16912,8 @@
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "dev": true
},
"is-fullwidth-code-point": {
"version": "3.0.0",
@@ -16875,6 +16924,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
"requires": {
"is-extglob": "^2.1.1"
}
@@ -16894,7 +16944,8 @@
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
},
"is-path-cwd": {
"version": "2.2.0",
@@ -17318,8 +17369,7 @@
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz",
"integrity": "sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"karma-source-map-support": {
"version": "1.4.0",
@@ -17541,6 +17591,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
"requires": {
"yallist": "^4.0.0"
}
@@ -17549,6 +17600,7 @@
"version": "0.25.7",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
+ "dev": true,
"requires": {
"sourcemap-codec": "^1.4.4"
}
@@ -18024,7 +18076,8 @@
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
},
"normalize-range": {
"version": "0.1.2",
@@ -18557,7 +18610,8 @@
"picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
},
"pify": {
"version": "2.3.0",
@@ -18673,8 +18727,7 @@
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.0.tgz",
"integrity": "sha512-FvO2GzMUaTN0t1fBULDeIvxr5IvbDXcIatt6pnJghc736nqNgsGao5NT+5+WVLAQiTt6Cb3YUms0jiPaXhL//g==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-custom-properties": {
"version": "12.1.4",
@@ -18744,15 +18797,13 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz",
"integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-gap-properties": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz",
"integrity": "sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-image-set-function": {
"version": "4.0.6",
@@ -18778,8 +18829,7 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz",
"integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-lab-function": {
"version": "4.1.1",
@@ -18806,22 +18856,19 @@
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz",
"integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-media-minmax": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz",
"integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-modules-extract-imports": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-modules-local-by-default": {
"version": "4.0.0",
@@ -18865,15 +18912,13 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz",
"integrity": "sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-page-break": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz",
"integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-place": {
"version": "7.0.4",
@@ -18938,8 +18983,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz",
"integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"postcss-selector-not": {
"version": "5.0.0",
@@ -19113,6 +19157,7 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
"requires": {
"picomatch": "^2.2.1"
}
@@ -19120,7 +19165,8 @@
"reflect-metadata": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
- "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg=="
+ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==",
+ "dev": true
},
"regenerate": {
"version": "1.4.2",
@@ -19395,8 +19441,7 @@
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"json-schema-traverse": {
"version": "0.4.1",
@@ -19425,6 +19470,7 @@
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
@@ -19740,7 +19786,8 @@
"sourcemap-codec": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
- "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
+ "dev": true
},
"spdy": {
"version": "4.0.2",
@@ -19948,8 +19995,7 @@
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"json-schema-traverse": {
"version": "0.4.1",
@@ -20023,6 +20069,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
"requires": {
"is-number": "^7.0.0"
}
@@ -20091,7 +20138,8 @@
"typescript": {
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
- "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA=="
+ "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
+ "dev": true
},
"ua-parser-js": {
"version": "0.7.31",
@@ -20300,8 +20348,7 @@
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"json-schema-traverse": {
"version": "0.4.1",
@@ -20537,8 +20584,7 @@
"version": "8.2.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
- "dev": true,
- "requires": {}
+ "dev": true
},
"y18n": {
"version": "5.0.8",
@@ -20548,7 +20594,8 @@
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
},
"yaml": {
"version": "1.10.2",
diff --git a/frontend/src/app/Shared.ts b/frontend/src/app/Shared.ts
index 7be29cbf..59a2716d 100644
--- a/frontend/src/app/Shared.ts
+++ b/frontend/src/app/Shared.ts
@@ -2,6 +2,7 @@ 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';
+import { YesNoDialogComponent } from './_modals/yes-no-dialog/yes-no-dialog.component';
class Shared {
constructor(
@@ -26,6 +27,18 @@ class Shared {
});
}
}
+ openYesNoDialog(title: string, message: string,yesFunction:Function): void {
+
+ if (this.dialog) {
+ const dialogRef = this.dialog.open(YesNoDialogComponent, {
+ width: '350px',
+ data: { title: title, message: message,yesFunction}
+ });
+ dialogRef.afterClosed().subscribe(res => {
+ //nesto
+ });
+ }
+ }
}
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
index 87f27d12..732d1c56 100644
--- a/frontend/src/app/_data/Dataset.ts
+++ b/frontend/src/app/_data/Dataset.ts
@@ -15,6 +15,7 @@ export default class Dataset {
public hasHeader: boolean = true,
public columnInfo: ColumnInfo[] = [],
+ public rowCount: number = 0,
public nullRows: number = 0,
public nullCols: number = 0,
public preview: string[][] = [[]]
diff --git a/frontend/src/app/_data/Experiment.ts b/frontend/src/app/_data/Experiment.ts
index a5aad218..453f6ca0 100644
--- a/frontend/src/app/_data/Experiment.ts
+++ b/frontend/src/app/_data/Experiment.ts
@@ -2,7 +2,7 @@ export default class Experiment {
_id: string = '';
uploaderId: string = '';
constructor(
- public name: string = 'Novi experiment',
+ public name: string = 'Novi eksperiment',
public description: string = '',
public datasetId: string = '',
public inputColumns: string[] = [],
@@ -10,7 +10,16 @@ export default class Experiment {
public nullValues: NullValueOptions = NullValueOptions.DeleteRows,
public nullValuesReplacers: NullValReplacer[] = [],
public dateCreated: Date = new Date(),
- public lastUpdated: Date = new Date()
+ public lastUpdated: Date = new Date(),
+ public modelIds: string[] = [],
+
+ // Test set settings
+ public randomOrder: boolean = true,
+ public randomTestSet: boolean = true,
+ public randomTestSetDistribution: number = 0.1, //0.1-0.9 (10% - 90%) JESTE OVDE ZAKUCANO 10, AL POSLATO JE KAO 0.1 BACK-U
+
+ //TODO - za svaku kolonu se bira enkoding
+ public encoding: Encoding = Encoding.Label
) { }
}
@@ -32,4 +41,28 @@ export class NullValReplacer {
"column": string;
"option": NullValueOptions;
"value": string;
+}
+
+export enum Encoding {
+ Label = 'label',
+ OneHot = 'onehot',
+ Ordinal = 'ordinal',
+ Hashing = 'hashing',
+ Binary = 'binary',
+ BaseN = 'baseN'
+ /*
+ BackwardDifference = 'backward difference',
+ CatBoost = 'cat boost',
+ Count = 'count',
+ GLMM = 'glmm',
+ Target = 'target',
+ Helmert = 'helmert',
+ JamesStein = 'james stein',
+ LeaveOneOut = 'leave one out',
+ MEstimate = 'MEstimate',
+ Sum = 'sum',
+ Polynomial = 'polynomial',
+ WOE = 'woe',
+ Quantile = 'quantile'
+ */
} \ No newline at end of file
diff --git a/frontend/src/app/_data/Model.ts b/frontend/src/app/_data/Model.ts
index 9ea437b1..8a85e296 100644
--- a/frontend/src/app/_data/Model.ts
+++ b/frontend/src/app/_data/Model.ts
@@ -7,16 +7,10 @@ export default class Model {
public description: string = '',
public dateCreated: Date = new Date(),
public lastUpdated: Date = new Date(),
- public experimentId: string = '',
-
- // Test set settings
- public randomOrder: boolean = true,
- public randomTestSet: boolean = true,
- public randomTestSetDistribution: number = 0.1, //0.1-0.9 (10% - 90%) JESTE OVDE ZAKUCANO 10, AL POSLATO JE KAO 0.1 BACK-U
+ //public experimentId: string = '',
// Neural net training settings
public type: ProblemType = ProblemType.Regression,
- public encoding: Encoding = Encoding.Label,
public optimizer: Optimizer = Optimizer.Adam,
public lossFunction: LossFunction = LossFunction.MeanSquaredError,
public inputNeurons: number = 1,
@@ -39,29 +33,6 @@ export enum ProblemType {
// replaceMissing srednja vrednost mean, median, najcesca vrednost (mode)
// removeOutliers
-export enum Encoding {
- Label = 'label',
- OneHot = 'onehot',
- Ordinal = 'ordinal',
- Hashing = 'hashing',
- Binary = 'binary',
- BaseN = 'baseN'
- /*
- BackwardDifference = 'backward difference',
- CatBoost = 'cat boost',
- Count = 'count',
- GLMM = 'glmm',
- Target = 'target',
- Helmert = 'helmert',
- JamesStein = 'james stein',
- LeaveOneOut = 'leave one out',
- MEstimate = 'MEstimate',
- Sum = 'sum',
- Polynomial = 'polynomial',
- WOE = 'woe',
- Quantile = 'quantile'
- */
-}
export enum ActivationFunction {
// linear
diff --git a/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.html b/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.html
index eb68b54c..bff8b022 100644
--- a/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.html
+++ b/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.html
@@ -41,9 +41,9 @@
</div>
<div class="px-5 mt-5">
- <app-datatable [data]="csvRecords" [hasHeader]="dataset.hasHeader"></app-datatable>
+ <app-datatable [tableData]="tableData"></app-datatable>
</div>
-<div class="d-flex flex-row align-items-center justify-content-center w-100">
+<div class="d-flex flex-row align-items-center justify-content-center w-100 my-2">
<button (click)="uploadDataset()" class="btn btn-lg col-4" style="background-color:#003459; color:white;">Dodaj izvor podataka</button>
</div>
diff --git a/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.ts b/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.ts
index 7421fbcf..3adc16f3 100644
--- a/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.ts
+++ b/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.ts
@@ -4,7 +4,8 @@ import Dataset from 'src/app/_data/Dataset';
import { DatasetsService } from 'src/app/_services/datasets.service';
import { ModelsService } from 'src/app/_services/models.service';
import shared from 'src/app/Shared';
-import { DatatableComponent } from '../datatable/datatable.component';
+import { DatatableComponent, TableData } from '../datatable/datatable.component';
+import { CsvParseService } from 'src/app/_services/csv-parse.service';
@Component({
selector: 'app-add-new-dataset',
@@ -14,13 +15,10 @@ import { DatatableComponent } from '../datatable/datatable.component';
export class AddNewDatasetComponent {
@Output() newDatasetAdded = new EventEmitter<string>();
- @ViewChild(DatatableComponent) datatable?: DatatableComponent;
+ @ViewChild(DatatableComponent) datatable!: DatatableComponent;
delimiterOptions: Array<string> = [",", ";", "\t", "razmak", "|"]; //podrazumevano ","
- //hasHeader: boolean = true;
- hasInput: boolean = false;
-
csvRecords: any[] = [];
files: File[] = [];
rowsNumber: number = 0;
@@ -28,7 +26,9 @@ export class AddNewDatasetComponent {
dataset: Dataset; //dodaj ! potencijalno
- constructor(private ngxCsvParser: NgxCsvParser, private modelsService: ModelsService, private datasetsService: DatasetsService) {
+ tableData: TableData = new TableData();
+
+ constructor(private modelsService: ModelsService, private datasetsService: DatasetsService, private csv: CsvParseService) {
this.dataset = new Dataset();
}
@@ -39,12 +39,13 @@ export class AddNewDatasetComponent {
if (this.files.length == 0 || this.files[0] == null) {
//console.log("NEMA FAJLA");
//this.loaded.emit("not loaded");
- this.hasInput = false;
+ this.tableData.hasInput = false;
return;
}
else
- this.hasInput = true;
+ this.tableData.hasInput = true;
+ this.tableData.loaded = false;
this.update();
}
@@ -53,34 +54,27 @@ export class AddNewDatasetComponent {
if (this.files.length < 1)
return;
- this.datatable!.loaded = false;
- this.datatable!.hasInput = this.hasInput;
-
- this.ngxCsvParser.parse(this.files[0], { header: false, delimiter: (this.dataset.delimiter == "razmak") ? " " : (this.dataset.delimiter == "") ? "," : this.dataset.delimiter })
- .pipe().subscribe((result) => {
-
- console.log('Result', result);
- if (result.constructor === Array) {
- if(this.dataset.hasHeader)
- this.csvRecords = result.splice(0,11);
- else
- this.csvRecords=result.splice(0,10);
- if (this.dataset.hasHeader)
- this.rowsNumber = this.csvRecords.length - 1;
- else
- this.rowsNumber = this.csvRecords.length;
- this.colsNumber = this.csvRecords[0].length;
-
- if (this.dataset.hasHeader)
- this.dataset.header = this.csvRecords[0];
-
- this.datatable!.data = this.csvRecords;
- this.datatable!.hasHeader = this.dataset.hasHeader;
- this.datatable!.loaded = true;
- }
- }, (error: NgxCSVParserError) => {
- console.log('Error', error);
- });
+ const fileReader = new FileReader();
+ fileReader.onload = (e) => {
+ if (typeof fileReader.result === 'string') {
+ const result = this.csv.csvToArray(fileReader.result, (this.dataset.delimiter == "razmak") ? " " : (this.dataset.delimiter == "") ? "," : this.dataset.delimiter)
+
+ if (this.dataset.hasHeader)
+ this.csvRecords = result.splice(0, 11);
+ else
+ this.csvRecords = result.splice(0, 10);
+
+ this.colsNumber = result[0].length;
+ this.rowsNumber = result.length;
+
+ this.tableData.data = this.csvRecords
+ this.tableData.hasHeader = this.dataset.hasHeader;
+ this.tableData.loaded = true;
+ this.tableData.numCols = this.colsNumber;
+ this.tableData.numRows = this.rowsNumber;
+ }
+ }
+ fileReader.readAsText(this.files[0]);
}
checkAccessible() {
@@ -96,17 +90,17 @@ export class AddNewDatasetComponent {
this.modelsService.uploadData(this.files[0]).subscribe((file) => {
//console.log('ADD MODEL: STEP 2 - ADD DATASET WITH FILE ID ' + file._id);
- this.dataset.fileId = file._id;
- this.dataset.username = shared.username;
-
- this.datasetsService.addDataset(this.dataset).subscribe((dataset) => {
- this.newDatasetAdded.emit("added");
- shared.openDialog("Obaveštenje", "Uspešno ste dodali novi izvor podataka u kolekciju. Molimo sačekajte par trenutaka da se procesira.");
- }, (error) => {
- shared.openDialog("Neuspeo pokušaj!", "Izvor podataka sa unetim nazivom već postoji u Vašoj kolekciji. Izmenite naziv ili iskoristite postojeći dataset.");
- }); //kraj addDataset subscribe
+ this.dataset.fileId = file._id;
+ this.dataset.username = shared.username;
+
+ this.datasetsService.addDataset(this.dataset).subscribe((dataset) => {
+ this.newDatasetAdded.emit("added");
+ shared.openDialog("Obaveštenje", "Uspešno ste dodali novi izvor podataka u kolekciju. Molimo sačekajte par trenutaka da se procesira.");
+ }, (error) => {
+ shared.openDialog("Neuspeo pokušaj!", "Izvor podataka sa unetim nazivom već postoji u Vašoj kolekciji. Izmenite naziv ili iskoristite postojeći dataset.");
+ }); //kraj addDataset subscribe
}, (error) => {
-
+
}); //kraj uploadData subscribe
}
diff --git a/frontend/src/app/_elements/dataset-load/dataset-load.component.html b/frontend/src/app/_elements/dataset-load/dataset-load.component.html
index 09487b3b..6ab58021 100644
--- a/frontend/src/app/_elements/dataset-load/dataset-load.component.html
+++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.html
@@ -30,7 +30,7 @@
</ul>
</div>
<div class="px-5 mt-5">
- <app-datatable [data]="datasetFile" [hasHeader]="datasetHasHeader"></app-datatable>
+ <app-datatable [tableData]="tableData"></app-datatable>
</div>
</div>
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 7329033c..dc78ab77 100644
--- a/frontend/src/app/_elements/dataset-load/dataset-load.component.ts
+++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.ts
@@ -3,7 +3,7 @@ import { AddNewDatasetComponent } from '../add-new-dataset/add-new-dataset.compo
import { ModelsService } from 'src/app/_services/models.service';
import shared from 'src/app/Shared';
import Dataset from 'src/app/_data/Dataset';
-import { DatatableComponent } from 'src/app/_elements/datatable/datatable.component';
+import { DatatableComponent, TableData } from 'src/app/_elements/datatable/datatable.component';
import { DatasetsService } from 'src/app/_services/datasets.service';
import { CsvParseService } from 'src/app/_services/csv-parse.service';
import { Output, EventEmitter } from '@angular/core';
@@ -17,8 +17,8 @@ export class DatasetLoadComponent {
@Output() selectedDatasetChangeEvent = new EventEmitter<Dataset>();
- @ViewChild(AddNewDatasetComponent) addNewDatasetComponent?: AddNewDatasetComponent;
- @ViewChild(AddNewDatasetComponent) datatable?: DatatableComponent;
+ @ViewChild(AddNewDatasetComponent) addNewDatasetComponent!: AddNewDatasetComponent;
+ @ViewChild(AddNewDatasetComponent) datatable!: DatatableComponent;
datasetLoaded: boolean = false;
selectedDatasetLoaded: boolean = false;
@@ -27,10 +27,8 @@ export class DatasetLoadComponent {
myDatasets?: Dataset[];
existingDatasetSelected: boolean = false;
selectedDataset?: Dataset;
- otherDataset?: Dataset;
- otherDatasetFile?: any[];
- datasetFile?: any[];
- datasetHasHeader?: boolean = true;
+
+ tableData: TableData = new TableData();
term: string = "";
@@ -63,27 +61,20 @@ export class DatasetLoadComponent {
this.selectedDataset = dataset;
this.selectedDatasetLoaded = false;
this.existingDatasetSelected = true;
- this.datasetHasHeader = this.selectedDataset.hasHeader;
+ this.tableData.hasHeader = this.selectedDataset.hasHeader;
+
+ this.tableData.hasInput = true;
+ this.tableData.loaded = false;
this.datasets.getDatasetFile(dataset.fileId).subscribe((file: string | undefined) => {
if (file) {
- console.log(file);
- this.datatable!.hasInput = true;
- this.datatable!.loaded = true;
- this.datasetFile = this.csv.csvToArray(file, (dataset.delimiter == "razmak") ? " " : (dataset.delimiter == "") ? "," : dataset.delimiter);
- /*for (let i = this.datasetFile.length - 1; i >= 0; i--) { //moguce da je vise redova na kraju fajla prazno i sl.
- if (this.datasetFile[i].length != this.datasetFile[0].length)
- this.datasetFile[i].pop();
- else
- break; //nema potrebe dalje
- }*/
- console.log(this.datatable!.data);
- console.log(this.datasetFile);
- console.log(this.datatable!.hasInput);
+ this.tableData.loaded = true;
+ this.tableData.numRows = this.selectedDataset!.rowCount;
+ this.tableData.numCols = this.selectedDataset!.columnInfo.length;
+ this.tableData.data = this.csv.csvToArray(file, (dataset.delimiter == "razmak") ? " " : (dataset.delimiter == "") ? "," : dataset.delimiter);
//this.resetCbsAndRbs(); //TREBA DA SE DESI
//this.refreshThreeNullValueRadioOptions(); //TREBA DA SE DESI
this.selectedDatasetLoaded = true;
- //this.scrollToNextForm();
this.selectedDatasetChangeEvent.emit(this.selectedDataset);
}
@@ -91,17 +82,7 @@ export class DatasetLoadComponent {
}
resetSelectedDataset(): boolean {
- const temp = this.selectedDataset;
- this.selectedDataset = this.otherDataset;
- this.otherDataset = temp;
- const tempFile = this.datasetFile;
- this.datasetFile = this.otherDatasetFile;
- this.otherDatasetFile = tempFile;
-
this.selectedDatasetChangeEvent.emit(this.selectedDataset);
-
return true;
}
-
-
}
diff --git a/frontend/src/app/_elements/datatable/datatable.component.html b/frontend/src/app/_elements/datatable/datatable.component.html
index b6cbd303..8db62aff 100644
--- a/frontend/src/app/_elements/datatable/datatable.component.html
+++ b/frontend/src/app/_elements/datatable/datatable.component.html
@@ -1,39 +1,43 @@
-PRE IFA
-{{hasInput}}
-<div *ngIf="data && hasInput">
- PROSLO IF
- <div class="table-responsive" style="height: 34rem; overflow: auto; border-radius: 5px;" class="mh-5">
- <div *ngIf="!loaded" style="background-color: #003459; width: 100%; height: 100%;"
+<div *ngIf="tableData.hasInput">
+ <div>
+ <div *ngIf="!tableData.loaded" backgroundColor="secondary" style="width: 100%; height: 100%;"
class="d-flex justify-content-center align-items-center">
<app-loading></app-loading>
</div>
- <div *ngIf="loaded">
- <table *ngIf="data.length > 0 && hasHeader && data[0].length > 0" class="table table-bordered table-light">
- <thead>
- <tr>
- <th *ngFor="let item of data[0]; let i = index">{{item}}</th>
- </tr>
- </thead>
- <tbody>
- <tr *ngFor="let row of data | slice:1">
- <td *ngFor="let col of row">{{col}}</td>
- </tr>
- </tbody>
- </table>
-
- <table *ngIf="data.length > 0 && !hasHeader && data[0].length > 0" class="table table-bordered table-light">
- <tbody>
- <tr *ngFor="let row of data">
- <td *ngFor="let col of row">{{col}}</td>
- </tr>
- </tbody>
- </table>
+ <div *ngIf="tableData.loaded && tableData.data">
+ <div id="info" *ngIf="tableData.data.length > 0 && tableData.data[0].length > 0"
+ class="d-flex flex-row justify-content-center align-items-center">
+ <div class="fs-5 mb-3">
+ Tabela {{tableData.numCols}}x{{tableData.numRows}}
+ </div>
+ </div>
+ <div class="table-responsive" style="overflow: auto; border-radius: 5px;">
+ <table *ngIf="tableData.data.length > 0 && tableData.hasHeader && tableData.data[0].length > 0" class="table table-bordered table-light">
+ <thead>
+ <tr>
+ <th *ngFor="let item of tableData.data[0]; let i = index">{{item}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let row of tableData.data | slice:1">
+ <td *ngFor="let col of row">{{col}}</td>
+ </tr>
+ <tr>
+ <td colspan="100" class="text-lg-center fs-6">+ {{tableData.numRows - 11}} redova...</td>
+ </tr>
+ </tbody>
+ </table>
+ <table *ngIf="tableData.data.length > 0 && !tableData.hasHeader && tableData.data[0].length > 0" class="table table-bordered table-light">
+ <tbody>
+ <tr *ngFor="let row of tableData.data">
+ <td *ngFor="let col of row">{{col}}</td>
+ </tr>
+ <tr>
+ <td colspan="100" class="text-lg-center fs-6">+ {{tableData.numRows - 10}} redova...</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
</div>
</div>
-
- <div id="info" *ngIf="data.length > 0 && data[0].length > 0">
- <br>
- <span *ngIf="hasHeader">{{data.length - 1}} x {{data[0].length}}</span>
- <span *ngIf="!hasHeader">{{data.length}} x {{data[0].length}}</span>
- </div>
</div> \ No newline at end of file
diff --git a/frontend/src/app/_elements/datatable/datatable.component.ts b/frontend/src/app/_elements/datatable/datatable.component.ts
index 19fb204e..82374f4d 100644
--- a/frontend/src/app/_elements/datatable/datatable.component.ts
+++ b/frontend/src/app/_elements/datatable/datatable.component.ts
@@ -7,12 +7,7 @@ import { Component, Input, OnInit } from '@angular/core';
})
export class DatatableComponent implements OnInit {
- @Input() hasHeader?: boolean = true;
-
- @Input() data?: any[] = [];
-
- hasInput = false;
- loaded = false;
+ @Input() tableData!: TableData;
constructor() { }
@@ -20,3 +15,14 @@ export class DatatableComponent implements OnInit {
}
}
+
+export class TableData {
+ constructor(
+ public hasHeader = true,
+ public hasInput = false,
+ public loaded = false,
+ public numRows = 0,
+ public numCols = 0,
+ public data?: any[][]
+ ) { }
+}
diff --git a/frontend/src/app/_elements/item-dataset/item-dataset.component.css b/frontend/src/app/_elements/item-dataset/item-dataset.component.css
index e69de29b..dc851671 100644
--- a/frontend/src/app/_elements/item-dataset/item-dataset.component.css
+++ b/frontend/src/app/_elements/item-dataset/item-dataset.component.css
@@ -0,0 +1,23 @@
+.card{
+ margin-top:0;
+ padding: 0;
+}
+.p-2{
+ margin: 0;
+ padding: 0;
+}
+hr{
+ margin: 0;
+ padding: 0;
+}
+b{
+ margin-left: 5px;
+ margin-right: 10px;
+}
+th{
+ margin: 10px;
+ padding: 10px;
+}
+p{
+ text-align: justify;
+} \ No newline at end of file
diff --git a/frontend/src/app/_elements/item-dataset/item-dataset.component.html b/frontend/src/app/_elements/item-dataset/item-dataset.component.html
index dc4221f4..11ff61c3 100644
--- a/frontend/src/app/_elements/item-dataset/item-dataset.component.html
+++ b/frontend/src/app/_elements/item-dataset/item-dataset.component.html
@@ -1,16 +1,41 @@
<div class="card" style="min-width: 12rem;">
- <div class="card-header">
- {{dataset.name}}
+<div class="card-header d-flex mb-2 justify-content-" style="padding: 0;margin: 0;">
+
+ <div class=" p-2 float-left "><b style="color: gray;">Naziv</b></div>
+ <div class=" p-2 float-left"><b>{{dataset.name}}</b></div>
+</div>
+<div class="card-body overflow-hidden">
+ <b style="color: gray;">Opis</b>
+ <hr style="width: 20%;"> <p> {{dataset.description}}</p>
+ <hr>
+ <div class="d-flex justify-content-center">
+ <div class=" p-2" >
+ <h4><span class="badge bg-secondary">{{dataset.extension}}</span></h4>
+ </div>
+ <div class="p-2">
+ <span class="material-icons">{{visibleicon}}</span>
+ </div>
+ <div class="p-2">
+ <span class="material-icons">{{accessibleicon}}</span>
+ </div>
</div>
- <div class="card-body overflow-hidden">
- <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>
- <!-- treba da se namesti da kad nema hedere, da korisnik unese nazive kolona pa da se taj heder prikaze -->
- </thead>
- </table>
- </div>
-</div> \ No newline at end of file
+ <hr>
+ <div class="col text-center">
+<button (click)=toggleDisplayDiv() class="btn btn-primary btn-sm active " mat-raised-button color="primary" style="margin: 0.5rem;">Kolone</button>
+ <div [hidden]="isShowDiv" style="overflow: scroll; overflow-y: hidden;">
+ <table class="table table-bordered table-md" >
+ <thead>
+ <th scope="col" *ngFor="let column of dataset.columnInfo" >{{column.columnName}}</th>
+ </thead>
+ </table>
+ </div>
+</div>
+ <table>
+ <tr><td><span class="material-icons">calendar_today</span></td><td><span style="color: grey;"> <b> Kreirano</b></span></td><td>{{dataset.dateCreated |date}}</td></tr>
+ <tr><td><span class="material-icons">edit_calendar</span></td><td><span style="color: grey;"> <b> Poslednja izmena</b></span></td><td>{{dataset.lastUpdated |date}}</td></tr>
+ </table>
+
+</div>
+<div class="card-footer">
+
+ </div> \ No newline at end of file
diff --git a/frontend/src/app/_elements/item-dataset/item-dataset.component.ts b/frontend/src/app/_elements/item-dataset/item-dataset.component.ts
index e12de34d..44b95310 100644
--- a/frontend/src/app/_elements/item-dataset/item-dataset.component.ts
+++ b/frontend/src/app/_elements/item-dataset/item-dataset.component.ts
@@ -9,7 +9,32 @@ import Dataset from 'src/app/_data/Dataset';
export class ItemDatasetComponent {
@Input() dataset: Dataset = new Dataset();
-
+ visibleicon='';
+ accessibleicon='';
+ isShowDiv = true;
+ toggleDisplayDiv() {
+ this.isShowDiv = !this.isShowDiv;
+ }
constructor() {
}
+ ngOnInit(): void {
+ if(this.dataset.isPublic==true)
+ {
+ this.visibleicon='visibility'
+ }
+ else
+ {
+ this.visibleicon='visibility_off';
+ }
+
+ if(this.dataset.accessibleByLink==true)
+ {
+ this.accessibleicon='link'
+ }
+ else
+ {
+ this.accessibleicon='link_off';
+ }
+ }
}
+
diff --git a/frontend/src/app/_elements/item-experiment/item-experiment.component.css b/frontend/src/app/_elements/item-experiment/item-experiment.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_elements/item-experiment/item-experiment.component.css
diff --git a/frontend/src/app/_elements/item-experiment/item-experiment.component.html b/frontend/src/app/_elements/item-experiment/item-experiment.component.html
new file mode 100644
index 00000000..51fbfef3
--- /dev/null
+++ b/frontend/src/app/_elements/item-experiment/item-experiment.component.html
@@ -0,0 +1,10 @@
+<div class="card" style="min-width: 12rem;">
+ <div class="card-header">
+ Naziv eksperimenta: <b>{{experiment.name}}</b>
+ </div>
+ <div class="card-body overflow-hidden">
+ <p class="card-text">
+ Opis: {{experiment.description}}
+ </p>
+ </div>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_elements/item-experiment/item-experiment.component.spec.ts b/frontend/src/app/_elements/item-experiment/item-experiment.component.spec.ts
new file mode 100644
index 00000000..1da7d05d
--- /dev/null
+++ b/frontend/src/app/_elements/item-experiment/item-experiment.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ItemExperimentComponent } from './item-experiment.component';
+
+describe('ItemExperimentComponent', () => {
+ let component: ItemExperimentComponent;
+ let fixture: ComponentFixture<ItemExperimentComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ ItemExperimentComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ItemExperimentComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_elements/item-experiment/item-experiment.component.ts b/frontend/src/app/_elements/item-experiment/item-experiment.component.ts
new file mode 100644
index 00000000..31900d35
--- /dev/null
+++ b/frontend/src/app/_elements/item-experiment/item-experiment.component.ts
@@ -0,0 +1,15 @@
+import { Component, Input, OnInit } from '@angular/core';
+import Experiment from 'src/app/_data/Experiment';
+
+@Component({
+ selector: 'app-item-experiment',
+ templateUrl: './item-experiment.component.html',
+ styleUrls: ['./item-experiment.component.css']
+})
+export class ItemExperimentComponent{
+
+ @Input() experiment: Experiment = new Experiment();
+
+ constructor() { }
+
+}
diff --git a/frontend/src/app/_elements/item-model/item-model.component.css b/frontend/src/app/_elements/item-model/item-model.component.css
index e69de29b..5ea24c72 100644
--- a/frontend/src/app/_elements/item-model/item-model.component.css
+++ b/frontend/src/app/_elements/item-model/item-model.component.css
@@ -0,0 +1,23 @@
+.card{
+ margin: 0.5rem;
+ padding: 0;
+}
+.p-2{
+ margin: 0;
+ padding: 0;
+}
+hr{
+ margin: 0;
+ padding: 0;
+}
+b{
+ margin-left: 5px;
+ margin-right: 10px;
+}
+th{
+ margin: 10px;
+ padding: 10px;
+}
+p{
+ text-align: justify;
+} \ No newline at end of file
diff --git a/frontend/src/app/_elements/item-model/item-model.component.html b/frontend/src/app/_elements/item-model/item-model.component.html
index 695c580e..447f023e 100644
--- a/frontend/src/app/_elements/item-model/item-model.component.html
+++ b/frontend/src/app/_elements/item-model/item-model.component.html
@@ -1,13 +1,58 @@
<div class="card" style="min-width: 12rem;">
- <div class="card-header">
- {{model.name}}
+ <div class="card-header d-flex mb-2 justify-content-" style="padding: 0;margin: 0;">
+
+ <div class=" p-2 float-left "><b style="color: gray;">Naziv</b></div>
+ <div class=" p-2 float-left"><b>{{model.name}}</b></div>
</div>
- <div class="card-body overflow-hidden">
+ <div class="card-body overflow-hidden">
+ <app-graph [model]="model"></app-graph>
+ <br>
+ <b style="color: gray;">Opis</b><hr style="width: 20%;">
<p class="card-text">
- {{"Opis: "+ model.description}}<br>
- {{"Datum kreiranja: " + model.dateCreated}}<br>
- {{"Poslednje ažuriranje: " + model.lastUpdated}}<br>
+ {{model.description}}
</p>
- <app-graph [model]="model"></app-graph>
+ <hr>
+
+ <div>
+ <table>
+ <tr><td><span class="material-icons">calendar_today</span></td><td><span style="color: grey;"> <b> Kreirano</b></span></td><td>{{model.dateCreated |date}}</td></tr>
+ <tr><td><span class="material-icons">edit_calendar</span></td><td><span style="color: grey;"> <b> Poslednja izmena</b></span></td><td>{{model.lastUpdated |date}}</td></tr>
+ </table>
+ </div>
+
</div>
+ <button (click)=toggleDisplayDiv() class="btn btn-default btn-lg " mat-raised-button color="primary" style="margin: 0.5rem;">Parametri</button>
+ <div [hidden]="isShowDiv">
+ <!-- <table>
+ <tr>
+ <td><span style="color: grey;"> <b> Nasumično raspoređivanje podataka</b></span></td><td>{{randomOrd}}</td>
+ </tr>
+ <tr>
+ <td><span style="color: grey;"> <b> Podela podataka na trening i test skup</b></span></td><td>{{randomOrd}}</td>
+ </tr>
+ <tr>
+ <td><span style="color: grey;"> <b> Veličina skupa za treniranje</b></span></td><td>{{randomOrd}}</td>
+ </tr>
+ </table>-->
+ <hr>
+ <table>
+ <tr>
+ <td><span style="color: grey;"> <b> Tip problema</b></span></td><td>{{model.type}}</td>
+ </tr>
+ <tr>
+ <td><span style="color: grey;"> <b> Optimizator</b></span></td><td>{{model.optimizer}}</td>
+ </tr>
+ <tr>
+ <td> <span style="color: grey;"> <b> Funkcija gubitka</b></span></td><td>{{model.lossFunction}}</td>
+ </tr>
+ <tr>
+ <td><span style="color: grey;"> <b> Batch size</b></span></td><td>{{model.batchSize}}</td>
+ </tr>
+ <tr>
+ <td><span style="color: grey;"> <b> Broj epoha</b></span></td><td>{{model.epochs}}</td>
+ </tr>
+
+ </table>
+
+ </div>
</div> \ No newline at end of file
diff --git a/frontend/src/app/_elements/item-model/item-model.component.ts b/frontend/src/app/_elements/item-model/item-model.component.ts
index 7f85f43f..b837667b 100644
--- a/frontend/src/app/_elements/item-model/item-model.component.ts
+++ b/frontend/src/app/_elements/item-model/item-model.component.ts
@@ -9,10 +9,25 @@ import Model from 'src/app/_data/Model';
export class ItemModelComponent implements OnInit {
@Input() model: Model = new Model();
+ isShowDiv = true;
+ randomOrd='';
+ toggleDisplayDiv() {
+ this.isShowDiv = !this.isShowDiv;
+ }
+
constructor() { }
ngOnInit(): void {
+ /*if(this.model.randomOrder)
+ {
+ this.randomOrd='Da';
+ }
+ else
+ {
+ this.randomOrd='Ne';
+ }
+*/
}
}
diff --git a/frontend/src/app/_elements/model-load/model-load.component.html b/frontend/src/app/_elements/model-load/model-load.component.html
index 0923c895..833b7181 100644
--- a/frontend/src/app/_elements/model-load/model-load.component.html
+++ b/frontend/src/app/_elements/model-load/model-load.component.html
@@ -85,18 +85,6 @@
<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">
@@ -149,43 +137,6 @@
</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>
- <div class="border m-3">
- <div class="row p-2 m-2">
- <div class="col-4">
- <label for="splitYesNo" class="form-check-label">
- <h3>Podela test skupa:&nbsp;&nbsp;
- <input id="splitYesNo" class="form-check-input" type="checkbox"
- [checked]="newModel.randomTestSet"
- (change)="newModel.randomTestSet = !newModel.randomTestSet">
- </h3>
- </label>
- </div>
- <div class="col-8">
- trening
- <mat-slider style="width: 85%;" min="10" max="90" step="10" value="10"
- name="randomTestSetDistribution" thumbLabel [disabled]="!newModel.randomTestSet"
- [(ngModel)]="tempTestSetDistribution">
- </mat-slider>
- test
- </div>
- </div>
-
- <div class="row p-2 mx-2">
- <div class="col-4">
- <label for="percentage" class="form-label">Procenat podataka koji se uzima za trening
- skup:</label>
- </div>
- <div class="col-2">
- <input id="percentage" type="number" class="form-control" min="10" max="90" step="10" value="90"
- [(ngModel)]="tempTestSetDistribution" [disabled]="!newModel.randomTestSet">
- </div>
- </div>
</div>
<h3>Aktivacione funkcije:</h3>
diff --git a/frontend/src/app/_elements/model-load/model-load.component.ts b/frontend/src/app/_elements/model-load/model-load.component.ts
index ca6b8ea5..abf19d75 100644
--- a/frontend/src/app/_elements/model-load/model-load.component.ts
+++ b/frontend/src/app/_elements/model-load/model-load.component.ts
@@ -1,6 +1,6 @@
import { Component, OnInit, ViewChild, Output, EventEmitter } from '@angular/core';
import Shared from 'src/app/Shared';
-import Model, { ActivationFunction, Encoding, LossFunction, LossFunctionBinaryClassification, LossFunctionMultiClassification, LossFunctionRegression, Metrics, MetricsBinaryClassification, MetricsMultiClassification, MetricsRegression, NullValueOptions, Optimizer, ProblemType } from 'src/app/_data/Model';
+import Model, { ActivationFunction, LossFunction, LossFunctionBinaryClassification, LossFunctionMultiClassification, LossFunctionRegression, Metrics, MetricsBinaryClassification, MetricsMultiClassification, MetricsRegression, NullValueOptions, Optimizer, ProblemType } from 'src/app/_data/Model';
import { ModelsService } from 'src/app/_services/models.service';
import { GraphComponent } from '../graph/graph.component';
@@ -20,7 +20,6 @@ export class ModelLoadComponent implements OnInit {
selectedModel?: Model;
ProblemType = ProblemType;
- Encoding = Encoding;
ActivationFunction = ActivationFunction;
metrics: any = Metrics;
LossFunction = LossFunction;
@@ -32,7 +31,6 @@ export class ModelLoadComponent implements OnInit {
term: string = "";
selectedProblemType: string = '';
selectedMetrics = [];
- tempTestSetDistribution = 90;
lossFunction: any = LossFunction;
showMyModels: boolean = true;
@@ -64,7 +62,6 @@ export class ModelLoadComponent implements OnInit {
uploadModel() { //console.log(this.selectedModel);
this.getMetrics();
- this.newModel.randomTestSetDistribution = 1 - Math.round(this.tempTestSetDistribution / 100 * 10) / 10;
this.newModel.username = Shared.username;
this.modelsService.addModel(this.newModel).subscribe((response) => {
diff --git a/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.css b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.css
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.css
diff --git a/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.html b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.html
new file mode 100644
index 00000000..06e74093
--- /dev/null
+++ b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.html
@@ -0,0 +1,8 @@
+<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)="onYesClick()" style="background-color: lightgray;">Da</button>
+ <button mat-button cdkFocusInitial (click)="onNoClick()" style="background-color: lightgray;">Ne</button>
+</div> \ No newline at end of file
diff --git a/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.spec.ts b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.spec.ts
new file mode 100644
index 00000000..eecf6468
--- /dev/null
+++ b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import {YesNoDialogComponent } from './yes-no-dialog.component';
+
+describe('AlertDialogComponent', () => {
+ let component: YesNoDialogComponent;
+ let fixture: ComponentFixture<YesNoDialogComponent>;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [ YesNoDialogComponent ]
+ })
+ .compileComponents();
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(YesNoDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.ts b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.ts
new file mode 100644
index 00000000..de1cdd4f
--- /dev/null
+++ b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.ts
@@ -0,0 +1,33 @@
+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;
+ yesFunction:Function;
+}
+
+@Component({
+ selector: 'app-yes-no-dialog',
+ templateUrl: './yes-no-dialog.component.html',
+ styleUrls: ['./yes-no-dialog.component.css']
+})
+export class YesNoDialogComponent {
+
+ constructor(
+ public dialogRef: MatDialogRef<YesNoDialogComponent>,
+ @Inject(MAT_DIALOG_DATA) public data: DialogData,
+ //public dialog: MatDialog
+ ) {}
+
+ onNoClick(): void {
+ this.dialogRef.close();
+ }
+ onYesClick():void{
+ this.data.yesFunction();
+ this.dialogRef.close();
+ }
+
+
+}
diff --git a/frontend/src/app/_pages/my-datasets/my-datasets.component.css b/frontend/src/app/_pages/my-datasets/my-datasets.component.css
index e69de29b..57889937 100644
--- a/frontend/src/app/_pages/my-datasets/my-datasets.component.css
+++ b/frontend/src/app/_pages/my-datasets/my-datasets.component.css
@@ -0,0 +1,8 @@
+#header {
+ background-color: #003459;
+ padding-top: 20px;
+ padding-bottom: 15px;
+ text-align: center;
+ color: white;
+ border-radius: 5px;
+} \ No newline at end of file
diff --git a/frontend/src/app/_pages/my-datasets/my-datasets.component.html b/frontend/src/app/_pages/my-datasets/my-datasets.component.html
index d996bf31..0c83dc85 100644
--- a/frontend/src/app/_pages/my-datasets/my-datasets.component.html
+++ b/frontend/src/app/_pages/my-datasets/my-datasets.component.html
@@ -1,5 +1,8 @@
+<div id="header">
+ <h1>Moji setovi podataka</h1>
+</div>
<div id="wrapper">
- <div id="container" class="container p-5" style="background-color: white; min-height: 100%;">
+ <div id="container" class="container p-5" style="background-color: rgba(255, 255, 255, 0.8); min-height: 100%;">
<div class="row mt-3 mb-2 d-flex justify-content-center">
<div class="col-sm-6" style="margin-bottom: 10px;">
@@ -12,9 +15,10 @@
<div class="panel-footer row"><!-- panel-footer -->
<div class="col-xs-6 text-center">
<div>
- <button type="button" class="btn btn-default btn-lg" mat-raised-button color="primary" (click)="deleteThisDataset(dataset)">Obriši
- <span class="glyphicon glyphicon-chevron-right"></span>
- </button>
+ <div>
+ <button (click)="deleteThisDataset(dataset)" mat-raised-button color="warn" style="min-width: 10rem;float: right" ><mat-icon>delete</mat-icon></button>
+ </div>
+
</div>
</div>
</div><!-- end panel-footer -->
@@ -24,6 +28,7 @@
<h2>Nema rezultata</h2>
</div>
</div>
+
</div>
diff --git a/frontend/src/app/_pages/my-datasets/my-datasets.component.ts b/frontend/src/app/_pages/my-datasets/my-datasets.component.ts
index 1551a3c8..19a6832b 100644
--- a/frontend/src/app/_pages/my-datasets/my-datasets.component.ts
+++ b/frontend/src/app/_pages/my-datasets/my-datasets.component.ts
@@ -5,6 +5,7 @@ import Dataset from 'src/app/_data/Dataset';
import { JwtHelperService } from '@auth0/angular-jwt';
import { CookieService } from 'ngx-cookie-service';
import shared from 'src/app/Shared';
+import { share } from 'rxjs';
@Component({
selector: 'app-my-datasets',
@@ -41,17 +42,17 @@ export class MyDatasetsComponent implements OnInit {
*/
deleteThisDataset(dataset: Dataset): void{
- console.log("OK");
+ shared.openYesNoDialog('Brisanje seta podataka','Da li ste sigurni da želite da obrišete ovaj set podataka?',() => {
this.datasetsS.deleteDataset(dataset).subscribe((response) => {
console.log("OBRISANO JE", response);
//na kraju uspesnog
this.getAllMyDatasets();
}, (error) =>{
if (error.error == "Dataset with name = {name} deleted") {
- alert("Greška pri brisanju dataseta!");
+ shared.openDialog("Greška","Greška pri brisanju dataseta!");
}
});
-
+ });
}
getAllMyDatasets(): void{
@@ -61,5 +62,6 @@ deleteThisDataset(dataset: Dataset): void{
console.log(this.myDatasets);
});
}
+
}
diff --git a/frontend/src/app/_pages/my-models/my-models.component.css b/frontend/src/app/_pages/my-models/my-models.component.css
index e69de29b..19d29595 100644
--- a/frontend/src/app/_pages/my-models/my-models.component.css
+++ b/frontend/src/app/_pages/my-models/my-models.component.css
@@ -0,0 +1,12 @@
+button{
+ margin-left: 5%;
+ margin-right: 5%;
+}
+#header {
+ background-color: #003459;
+ padding-top: 20px;
+ padding-bottom: 15px;
+ text-align: center;
+ color: white;
+ border-radius: 5px;
+} \ No newline at end of file
diff --git a/frontend/src/app/_pages/my-models/my-models.component.html b/frontend/src/app/_pages/my-models/my-models.component.html
index 4aebc1f2..b0e9c4ef 100644
--- a/frontend/src/app/_pages/my-models/my-models.component.html
+++ b/frontend/src/app/_pages/my-models/my-models.component.html
@@ -1,5 +1,8 @@
+<div id="header">
+ <h1>Moji modeli</h1>
+</div>
<div id="wrapper">
- <div id="container" class="container p-5" style="background-color: white; min-height: 100%;">
+ <div id="container" class="container p-5" style="background-color: rgba(255, 255, 255, 0.8); min-height: 100%;">
<div class="row mt-3 mb-2 d-flex justify-content-center">
<div class="col-sm-6" style="margin-bottom: 10px;">
@@ -12,12 +15,12 @@
<div class="panel-footer row"><!-- panel-footer -->
<div class="col-xs-6 text-center">
<div>
- <button type="button" class="btn btn-default btn-lg" (click)="deleteThisModel(model)" mat-raised-button color="primary">Koristi
- <span class="glyphicon glyphicon-search"></span>
- </button>
- <button type="button" class="btn btn-default btn-lg" mat-raised-button color="primary" (click)="deleteThisModel(model)">Obriši
- <span class="glyphicon glyphicon-chevron-right"></span>
- </button>
+ <button type="button" class="btn btn-default btn-lg"style="min-width: 7rem;float: left;" (click)="deleteThisModel(model)" mat-raised-button color="primary">Koristi
+ <span class="glyphicon glyphicon-search"></span>
+ </button>
+ <button (click)="deleteThisModel(model)" mat-raised-button color="warn" style="min-width: 7rem;float: right" ><mat-icon>delete</mat-icon></button>
+
+
</div>
</div>
</div><!-- end panel-footer -->
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 6086b1b1..f3877e2d 100644
--- a/frontend/src/app/_pages/my-models/my-models.component.ts
+++ b/frontend/src/app/_pages/my-models/my-models.component.ts
@@ -32,7 +32,7 @@ export class MyModelsComponent implements OnInit {
*/
deleteThisModel(model: Model): void{
- console.log("OK");
+ shared.openYesNoDialog('Brisanje seta podataka','Da li ste sigurni da želite da obrišete model?',() => {
this.modelsS.deleteModel(model).subscribe((response) => {
console.log("OBRISANOOO JEE", response);
//na kraju uspesnog
@@ -42,9 +42,10 @@ deleteThisModel(model: Model): void{
shared.openDialog("Obaveštenje", "Greška prilikom brisanja modela.");
}
});
-
+ });
}
+
getAllMyModels(): void{
this.modelsS.getMyModels().subscribe(m => {
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 3746d35e..d38f93e4 100644
--- a/frontend/src/app/_pages/my-predictors/my-predictors.component.html
+++ b/frontend/src/app/_pages/my-predictors/my-predictors.component.html
@@ -1,7 +1,7 @@
<div id="header">
<h1>Trenirani modeli</h1>
</div>
-<div id="container" style="background-color:rgba(255, 255, 255, 0.747);">
+<div id="container" style="background-color:rgba(255, 255, 255, 0.8);">
<div class="row" *ngFor="let predictor of predictors">
<div class="left">
<app-item-predictor [predictor]="predictor"></app-item-predictor>
diff --git a/frontend/src/app/_services/experiments.service.ts b/frontend/src/app/_services/experiments.service.ts
index 60d1bfb2..ecb3e262 100644
--- a/frontend/src/app/_services/experiments.service.ts
+++ b/frontend/src/app/_services/experiments.service.ts
@@ -15,4 +15,8 @@ export class ExperimentsService {
addExperiment(experiment: Experiment): Observable<any> {
return this.http.post(`${API_SETTINGS.apiURL}/experiment/add`, experiment, { headers: this.authService.authHeader() });
}
+
+ getMyExperiments(): Observable<Experiment[]> {
+ return this.http.get<Experiment[]>(`${API_SETTINGS.apiURL}/experiment/getmyexperiments`, { headers: this.authService.authHeader() });
+ }
}
diff --git a/frontend/src/app/_services/models.service.ts b/frontend/src/app/_services/models.service.ts
index 3fbad109..9a1e71da 100644
--- a/frontend/src/app/_services/models.service.ts
+++ b/frontend/src/app/_services/models.service.ts
@@ -35,8 +35,8 @@ export class ModelsService {
addDataset(dataset: Dataset): Observable<any> {
return this.http.post(`${API_SETTINGS.apiURL}/dataset/add`, dataset, { headers: this.authService.authHeader() });
}
- trainModel(model: Model): Observable<any> {
- return this.http.post(`${API_SETTINGS.apiURL}/model/sendmodel`, model, { headers: this.authService.authHeader(), responseType: 'text' });
+ trainModel(modelId: string, experimentId: string): Observable<any> {
+ return this.http.post(`${API_SETTINGS.apiURL}/model/trainmodel`, { ModelId: modelId, ExperimentId: experimentId }, { headers: this.authService.authHeader(), responseType: 'text' });
}
getMyDatasets(): Observable<Dataset[]> {
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index 1b91a1ac..f57441c0 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -45,6 +45,8 @@ import { AlertDialogComponent } from './_modals/alert-dialog/alert-dialog.compon
import { AddNewDatasetComponent } from './_elements/add-new-dataset/add-new-dataset.component';
import { GraphComponent } from './_elements/graph/graph.component';
import { TrainingComponent } from './training/training.component';
+import { ItemExperimentComponent } from './_elements/item-experiment/item-experiment.component';
+import { YesNoDialogComponent } from './_modals/yes-no-dialog/yes-no-dialog.component';
@NgModule({
declarations: [
@@ -80,6 +82,8 @@ import { TrainingComponent } from './training/training.component';
AddNewDatasetComponent,
GraphComponent,
TrainingComponent,
+ ItemExperimentComponent,
+ YesNoDialogComponent
],
imports: [
BrowserModule,
diff --git a/frontend/src/app/experiment/experiment.component.html b/frontend/src/app/experiment/experiment.component.html
index 42797579..36cf9eda 100644
--- a/frontend/src/app/experiment/experiment.component.html
+++ b/frontend/src/app/experiment/experiment.component.html
@@ -13,7 +13,7 @@
</div>
<div id="carouselExampleControls" class="carousel slide" data-bs-wrap="false" data-bs-ride="carousel" data-bs-interval="false">
- <div class="carousel-inner border">
+ <div class="carousel-inner">
<div class="carousel-item active">
<h2>1. Izvor podataka</h2>
<app-dataset-load (selectedDatasetChangeEvent)="updateDataset($event)"></app-dataset-load>
@@ -21,7 +21,16 @@
<div class="carousel-item">
<h2>2. Preprocesiranje</h2>
- <h3>Biranje ulaznih i izlaznih kolona:</h3>
+
+ <label for="name" class="col-form-label">Naziv eksperimenta:</label>
+ <input type="text" class="form-control mb-1" name="name" placeholder="Naziv..." [(ngModel)]="experiment.name">
+
+ <label for="desc" class="col-sm-2 col-form-label">Opis:</label>
+ <div>
+ <textarea class="form-control" name="desc" rows="3" [(ngModel)]="experiment.description"></textarea>
+ </div>
+
+ <h3 class="mt-3">Biranje ulaznih i izlaznih kolona:</h3>
<div *ngIf="selectedDataset">
<div class="row">
<div class="col d-flex justify-content-center">
@@ -31,8 +40,9 @@
<div *ngFor="let item of selectedDataset.columnInfo; let i = index">
<input class="form-check-input" type="checkbox" value="{{item.columnName}}"
id="cb_{{item.columnName}}" name="cbsNew"
- [checked]="this.selectedOutputColumnVal != item.columnName"
- [disabled]="this.selectedOutputColumnVal == item.columnName">&nbsp;
+ [checked]="experiment.outputColumn != item.columnName"
+ [disabled]="experiment.outputColumn == item.columnName"
+ (click)="checkedColumnsChanged(item, 0)">&nbsp;
<label class="form-check-label" for="cb_{{item.columnName}}">
{{item.columnName}}
</label>
@@ -44,8 +54,11 @@
<div id="divOutputs" class="form-check mt-2">
<br>
<div *ngFor="let item of selectedDataset.columnInfo; let i = index">
- <input class="form-check-input" type="radio" value="{{item.columnName}}" id="rb_{{item.columnName}}"
- name="rbsNew" (change)="this.selectedOutputColumnVal = item.columnName">&nbsp;
+ <input class="form-check-input" type="radio" value="{{item.columnName}}"
+ id="rb_{{item.columnName}}" name="rbsNew"
+ [(ngModel)]="this.experiment.outputColumn"
+ (change)="experiment.outputColumn = item.columnName"
+ (click)="checkedColumnsChanged(item, 1);">&nbsp;
<label class="form-check-label" for="rb_{{item.columnName}}">
{{item.columnName}}
</label>
@@ -54,11 +67,12 @@
</div>
</div>
</div>
+ <br>
<h3>Popunjavanje nedostajućih vrednosti:</h3>
<div class="form-check" *ngIf="selectedDataset">
<input type="radio" [(ngModel)]="experiment.nullValues" [value]="NullValueOptions.DeleteRows"
- class="form-check-input" value="deleteRows" name="fillMissing" id="delRows" checked data-bs-toggle="collapse"
- data-bs-target="#fillMissingCustom.show">
+ class="form-check-input" value="deleteRows" name="fillMissing" id="delRows" checked
+ data-bs-toggle="collapse" data-bs-target="#fillMissingCustom.show">
<label for="delRows" class="form-check-label">Obriši sve
redove sa nedostajućim vrednostima ({{selectedDataset.nullRows}} / TODO)</label><br>
<input type="radio" [(ngModel)]="experiment.nullValues" [value]="NullValueOptions.DeleteColumns"
@@ -66,29 +80,38 @@
data-bs-target="#fillMissingCustom.show">
<label for="delCols" class="form-check-label">Obriši sve
kolone sa nedostajućim vrednostima ({{selectedDataset.nullCols}} / TODO)</label><br>
- <input type="radio" [(ngModel)]="experiment.nullValues" [value]="NullValueOptions.Replace" class="form-check-input"
- name="fillMissing" id="replace" data-bs-toggle="collapse" data-bs-target="#fillMissingCustom:not(.show)">
+ <input type="radio" [(ngModel)]="experiment.nullValues" [value]="NullValueOptions.Replace"
+ class="form-check-input" name="fillMissing" id="replace" data-bs-toggle="collapse"
+ data-bs-target="#fillMissingCustom:not(.show)">
<label for="replace" class="form-check-label">Izabraću
vrednosti koje će da zamene nedostajuće vrednosti za svaku kolonu...</label><br><br>
<div class="collapse" id="fillMissingCustom">
<div>
<label for="columnReplacers" class="form-label">Unesite zamenu za svaku kolonu:</label>
+ <div class="my-3" *ngIf="getSelectedNullColumnsArray().length > 0" >
+ <label class="text-center form-control mx-3 text-secondary">
+ Kolone <span style="font-style: italic;" *ngFor="let colname of getSelectedNullColumnsArray(); let i = index">
+ <span *ngIf="i != getSelectedNullColumnsArray().length - 1">{{colname}}, </span>
+ <span *ngIf="i == getSelectedNullColumnsArray().length - 1">{{colname}} </span>
+ </span>
+ nemaju nedostajućih vrednosti za popunjavanje.
+ </label>
+ </div>
<div id="columnReplacers">
- <div *ngFor="let column of selectedDataset.columnInfo; let i = index" class="my-3">
- <div *ngIf="getInputById('cb_'+column.columnName).checked || selectedOutputColumnVal == column.columnName"
- class="">
+ <div *ngFor="let column of selectedColumnsInfoArray; let i = index" class="my-3">
+ <div *ngIf="column.numNulls > 0">
<span class="w-20 mx-3">
- {{column.columnName}}&nbsp;<span class="small" style="color:gray;">({{column.numNulls}}
- null)
+ {{column.columnName}}&nbsp;<span class="small" style="color:gray;">({{column.numNulls}} null)
</span>
</span>
-
- <label *ngIf="column.numNulls <= 0" class="text-center form-control mx-3 text-secondary">
+
+ <label *ngIf="column.numNulls <= 0"
+ class="text-center form-control mx-3 text-secondary">
Ova kolona nema
nedostajućih
vrednosti.
</label>
-
+
<div *ngIf="column.numNulls > 0" class="d-flex flex-row justify-content-end">
<div class="flex-grow-3 mx-3 me-auto">
<div class="input-group">
@@ -100,20 +123,22 @@
</label>
</div>
<input type="text" class="form-control" [id]="'fillText_'+column.columnName"
- (keyup)="checkFillColRadio(column.columnName)" placeholder="Unesi vrednost...">
-
+ (keyup)="checkFillColRadio(column.columnName)"
+ placeholder="Unesi vrednost...">
+
<div class="input-group-append">
<select [id]="'replaceOptions'+i" class="form-control btn-primary"
- *ngIf="column.isNumber" (change)="replace($event, column);">
+ *ngIf="column.isNumber" (change)="replace($event, column); checkFillColRadio(column.columnName);">
<option
*ngFor="let option of Object.keys(ReplaceWith); let optionName of Object.values(ReplaceWith)"
[value]="option">
{{ optionName }}
</option>
</select>
- <select [id]="'replaceOptions'+i" class="form-control btn-outline-primary"
+ <select [id]="'replaceOptions'+i"
+ class="form-control btn-outline-primary"
*ngIf="!column.isNumber && column.numNulls > 0"
- (change)="replace($event, column);">
+ (change)="replace($event, column); checkFillColRadio(column.columnName);">
<option *ngFor="let option of column.uniqueValues" [value]="option">
{{ option }}
</option>
@@ -121,7 +146,7 @@
</div>
</div>
</div>
-
+
<div class="flex-shrink-1 mx-3">
<div class="input-group">
<label class="form-control" [for]="'delCol_'+column.columnName">Izbriši
@@ -131,7 +156,7 @@
(change)="emptyFillTextInput(column.columnName)"></label>
</div>
</div>
-
+
<div class="flex-shrink-1 mx-3">
<div class="input-group">
<label class="form-control" [for]="'delRows_'+column.columnName">Izbriši
@@ -196,6 +221,60 @@
</div>
</div>
+ <div id="randomOptions">
+ <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)]="experiment.randomOrder"
+ type="checkbox" value="" checked>
+ </div>
+ <div class="border m-3">
+ <div class="row p-2 m-2">
+ <div class="col-4">
+ <label for="splitYesNo" class="form-check-label">
+ <h3>Podela test skupa:&nbsp;&nbsp;
+ <input id="splitYesNo" class="form-check-input" type="checkbox"
+ [checked]="experiment.randomTestSet"
+ (change)="experiment.randomTestSet = !experiment.randomTestSet">
+ </h3>
+ </label>
+ </div>
+ <div class="col-8">
+ trening
+ <mat-slider style="width: 85%;" min="10" max="90" step="10" value="10"
+ name="randomTestSetDistribution" thumbLabel [disabled]="!experiment.randomTestSet"
+ [(ngModel)]="tempTestSetDistribution">
+ </mat-slider>
+ test
+ </div>
+ </div>
+
+ <div class="row p-2 mx-2">
+ <div class="col-4">
+ <label for="percentage" class="form-label">Procenat podataka koji se uzima za trening
+ skup:</label>
+ </div>
+ <div class="col-2">
+ <input id="percentage" type="number" class="form-control" min="10" max="90" step="10" value="90"
+ [(ngModel)]="tempTestSetDistribution" [disabled]="!experiment.randomTestSet">
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div id="encodingForColumns">
+ <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)]="experiment.encoding">
+ <option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)"
+ [value]="option">
+ {{ optionName }}
+ </option>
+ </select>
+ </div>
+ </div>
+
</div>
diff --git a/frontend/src/app/experiment/experiment.component.ts b/frontend/src/app/experiment/experiment.component.ts
index 7ccca528..8a1b7d70 100644
--- a/frontend/src/app/experiment/experiment.component.ts
+++ b/frontend/src/app/experiment/experiment.component.ts
@@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core';
-import Experiment, { NullValReplacer, NullValueOptions, ReplaceWith } from '../_data/Experiment';
+import Experiment, { NullValReplacer, NullValueOptions, ReplaceWith, Encoding } from '../_data/Experiment';
import Model from '../_data/Model';
import Dataset, { ColumnInfo } from '../_data/Dataset';
import { ModelsService } from '../_services/models.service';
@@ -20,12 +20,15 @@ export class ExperimentComponent implements OnInit {
NullValueOptions = NullValueOptions;
ReplaceWith = ReplaceWith;
+ Encoding = Encoding;
Object = Object;
selectedColumnsInfoArray: ColumnInfo[] = [];
- selectedOutputColumnVal: string = '';
+ //selectedOutputColumnVal: string = '';
selectedNullColumnsArray: string[] = [];
+ tempTestSetDistribution = 90;
+
constructor(private modelsService: ModelsService, private experimentsService: ExperimentsService) { }
ngOnInit(): void {
@@ -36,12 +39,7 @@ export class ExperimentComponent implements OnInit {
this.selectedDataset = dataset;
this.selectedColumnsInfoArray = this.selectedDataset.columnInfo;
this.selectedNullColumnsArray = [];
- console.log("array:", this.selectedColumnsInfoArray);
- }
-
- updateModel(model: Model) {
- //console.log(model);
- this.selectedModel = model;
+ //console.log("array:", this.selectedColumnsInfoArray);
}
getInputById(id: string): HTMLInputElement {
@@ -71,9 +69,9 @@ export class ExperimentComponent implements OnInit {
checkedColumnsChanged(checkedColumnInfo: ColumnInfo, buttonType: number) { //0-input,1-output
let col = this.selectedColumnsInfoArray.find(x => x.columnName == checkedColumnInfo.columnName);
if (buttonType == 0) { //inputCol
- if (col == undefined)
+ if (col == undefined)
this.selectedColumnsInfoArray.push(checkedColumnInfo);
- else
+ else
this.selectedColumnsInfoArray = this.selectedColumnsInfoArray.filter(x => x.columnName != checkedColumnInfo.columnName);
}
else { //outputCol
@@ -81,7 +79,7 @@ export class ExperimentComponent implements OnInit {
this.selectedColumnsInfoArray.push(checkedColumnInfo);
}
//console.log(this.selectedColumnsInfoArray);
- }
+ }
replace(event: Event, column: ColumnInfo) {
let option = (<HTMLInputElement>event.target).value;
@@ -170,21 +168,24 @@ export class ExperimentComponent implements OnInit {
Shared.openDialog("Greška", "Molimo Vas da izaberete ulazne kolone.");
return;
}
-
+
this.experiment._id = '';
this.experiment.uploaderId = '';
this.experiment.datasetId = this.selectedDataset._id;
-
+
let pom = this.selectedColumnsInfoArray.filter(x => x.columnName != this.experiment.outputColumn);
for (let i = 0; i < pom.length; i++)
this.experiment.inputColumns.push(pom[i].columnName);
- this.selectedColumnsInfoArray = this.selectedColumnsInfoArray.filter(x => x.numNulls > 0);
- //TREBAJU MI NULLVALUESREPLACERI
+ //this.experiment.outputColumn = this.selectedOutputColumnVal;
+
+ this.selectedColumnsInfoArray = this.selectedColumnsInfoArray.filter(x => x.numNulls > 0); //obavezno
this.experiment.nullValuesReplacers = this.getNullValuesReplacersArray();
- console.log("Eksperiment:", this.experiment);
-
+ this.experiment.randomTestSetDistribution = 1 - Math.round(this.tempTestSetDistribution / 100 * 10) / 10;
+
+ //console.log("Eksperiment:", this.experiment);
+
this.experimentsService.addExperiment(this.experiment).subscribe((response) => {
this.experiment = response;
@@ -193,25 +194,9 @@ export class ExperimentComponent implements OnInit {
Shared.openDialog("Obaveštenje", "Eksperiment je uspešno kreiran.");
}, (error) => {
-
- });
- }
-
- trainModel() {
- this.trainingResult = undefined;
- //console.log('Training model...', this.selectedModel);
- if (!this.selectedDataset) {
- Shared.openDialog('Greška', 'Izvor podataka nije izabran!');
- return;
- }
- // TODO proveri nullValues
- if (!this.selectedModel) {
- Shared.openDialog('Greška', 'Model nije izabran!');
- return;
- }
- this.modelsService.trainModel(this.selectedModel).subscribe((response: any) => {
- console.log('Train model complete!', response);
- this.trainingResult = response;
+ if (error.error == "Experiment with this name exists") {
+ Shared.openDialog("Greška", "Eksperiment sa unetim nazivom već postoji u Vašoj kolekciji. Unesite neki drugi naziv.");
+ }
});
}
}
diff --git a/frontend/src/app/training/training.component.css b/frontend/src/app/training/training.component.css
index ee4b0448..490c56b5 100644
--- a/frontend/src/app/training/training.component.css
+++ b/frontend/src/app/training/training.component.css
@@ -29,7 +29,7 @@
border-color: #003459;
}
-.selectedDatasetClass {
+.selectedExperimentClass {
/*border-color: 2px solid #003459;*/
background-color: lightblue;
}
diff --git a/frontend/src/app/training/training.component.html b/frontend/src/app/training/training.component.html
index 1939d3cf..2e574c12 100644
--- a/frontend/src/app/training/training.component.html
+++ b/frontend/src/app/training/training.component.html
@@ -4,13 +4,25 @@
<div id="wrapper">
<div id="container" class="container p-5" style="background-color: white; min-height: 100%;">
-<h2>1. Izaberi eksperiment</h2>
-TODO
+<h2>1. Izaberite eksperiment iz kolekcije</h2>
+<div class="px-5 my-2">
+ <input type="text" class="form-control" placeholder="Pretraga"
+ [(ngModel)]="term">
+</div>
+<div class="overflow-auto" style="max-height: 500px;">
+ <ul class="list-group">
+ <li class="list-group-item p-3" *ngFor="let experiment of myExperiments|filter:term"
+ [ngClass]="{'selectedExperimentClass': this.selectedExperiment == experiment}">
+ <app-item-experiment [experiment]="experiment"
+ (click)="selectThisExperiment(experiment);"></app-item-experiment>
+ </li>
+ </ul>
+</div>
-<h2>2.Izaberi model</h2>
+<h2>2.Izaberite model</h2>
<app-model-load (selectedModelChangeEvent)="selectModel($event)"></app-model-load>
-<h2>3. Treniraj model</h2>
+<h2>3. Trenirajte model</h2>
<button class="btn btn-lg col-4" style="background-color:#003459; color:white;" (click)="trainModel();">Treniraj
model</button>
diff --git a/frontend/src/app/training/training.component.ts b/frontend/src/app/training/training.component.ts
index cb6c304c..4f20bc87 100644
--- a/frontend/src/app/training/training.component.ts
+++ b/frontend/src/app/training/training.component.ts
@@ -1,29 +1,55 @@
import { Component, OnInit } from '@angular/core';
+import Shared from '../Shared';
import Experiment from '../_data/Experiment';
import Model from '../_data/Model';
+import { DatasetsService } from '../_services/datasets.service';
+import { ExperimentsService } from '../_services/experiments.service';
+import { ModelsService } from '../_services/models.service';
@Component({
selector: 'app-training',
templateUrl: './training.component.html',
styleUrls: ['./training.component.css']
})
-export class TrainingComponent implements OnInit {
-
- constructor() { }
-
- ngOnInit(): void {
- }
+export class TrainingComponent{
+ myExperiments?: Experiment[];
selectedExperiment?: Experiment;
selectedModel?: Model;
trainingResult: any;
- selectModel($model: Model) {
+ term: string = "";
+
+ constructor(private modelsService: ModelsService, private datasetsService: DatasetsService, private experimentsService: ExperimentsService) {
+ this.experimentsService.getMyExperiments().subscribe((experiments) => {
+ this.myExperiments = experiments;
+ console.log(this.myExperiments);
+ });
+ }
+
+ selectThisExperiment(experiment: Experiment) {
+ this.selectedExperiment = experiment;
+ }
+ selectModel(model: Model) {
+ this.selectedModel = model;
}
trainModel() {
- //eksperiment i model moraju da budu izabrani
+ this.trainingResult = undefined;
+
+ if (this.selectedExperiment == undefined) {
+ Shared.openDialog("Greška", "Molimo Vas da izaberete eksperiment iz kolekcije.");
+ return;
+ }
+ if (this.selectedModel == undefined) {
+ Shared.openDialog("Greška", "Molimo Vas da izaberete model.");
+ return;
+ }
+ this.modelsService.trainModel(this.selectedModel._id, this.selectedExperiment._id).subscribe((response: any) => {
+ console.log('Train model complete!', response);
+ this.trainingResult = response;
+ });
}
}