diff options
40 files changed, 534 insertions, 474 deletions
diff --git a/backend/api/api/Controllers/DatasetController.cs b/backend/api/api/Controllers/DatasetController.cs index add85aba..0a9fe0bd 100644 --- a/backend/api/api/Controllers/DatasetController.cs +++ b/backend/api/api/Controllers/DatasetController.cs @@ -25,22 +25,23 @@ namespace api.Controllers _fileService = fileService; jwtToken = Token; } - public string getUsername() + + public string getUserId() { - string username; + string userId; 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) + userId = jwtToken.TokenToId(parameter); + if (userId == null) return null; } else return null; - return username; + return userId; } // GET: api/<DatasetController>/mydatasets @@ -48,17 +49,17 @@ namespace api.Controllers [Authorize(Roles = "User,Guest")] public ActionResult<List<Dataset>> Get() { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); - if (username == "") + if (userId == "") return _datasetService.GetGuestDatasets(); //ako bude trebao ID, samo iz baze uzeti - return _datasetService.GetMyDatasets(username); + return _datasetService.GetMyDatasets(userId); } // GET: api/<DatasetController>/datesort/{ascdsc}/{latest} @@ -69,12 +70,12 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult<List<Dataset>> SortDatasets(bool ascdsc, int latest) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); - List<Dataset> lista = _datasetService.SortDatasets(username, ascdsc, latest); + List<Dataset> lista = _datasetService.SortDatasets(userId, ascdsc, latest); if (latest == 0) return lista; @@ -100,14 +101,7 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult<List<Dataset>> Search(string name) { - string username = getUsername(); - - if (username == null) - return BadRequest(); - - //ako bude trebao ID, samo iz baze uzeti - - return _datasetService.SearchDatasets(name, username); + return _datasetService.SearchDatasets(name); } @@ -117,12 +111,12 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult<Dataset> Get(string name) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); - var dataset = _datasetService.GetOneDataset(username, name); + var dataset = _datasetService.GetOneDataset(userId, name); if (dataset == null) return NotFound($"Dataset with name = {name} not found or dataset is not public or not preprocessed"); @@ -134,25 +128,15 @@ namespace api.Controllers [Authorize(Roles = "User,Guest")] public async Task<ActionResult<Dataset>> Post([FromBody] Dataset dataset) { - 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 - return BadRequest(); + string uploaderId = getUserId(); + //da li ce preko tokena da se ubaci username ili front salje //dataset.username = usernameToken; //username = "" ako je GUEST DODAO - var existingDataset = _datasetService.GetOneDataset(dataset.username, dataset.name); + var existingDataset = _datasetService.GetOneDataset(dataset.uploaderId, dataset.name); if (existingDataset != null) - return NotFound($"Dateset with name = {dataset.name} exisits"); + return NotFound($"Dataset with this name already exists"); else { FileModel fileModel = _fileService.getFile(dataset.fileId); @@ -169,20 +153,20 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult Put(string name, [FromBody] Dataset dataset) { - string username = getUsername(); + string uploaderId = getUserId(); - if (username == null) + if (uploaderId == null) return BadRequest(); - var existingDataset = _datasetService.GetOneDataset(username, name); + var existingDataset = _datasetService.GetOneDataset(uploaderId, name); //ne mora da se proverava if (existingDataset == null) - return NotFound($"Dataset with name = {name} or user with username = {username} not found"); + return NotFound($"Dataset with name = {name} or user with ID = {uploaderId} not found"); dataset.lastUpdated = DateTime.UtcNow; - _datasetService.Update(username, name, dataset); + _datasetService.Update(uploaderId, name, dataset); return Ok($"Dataset with name = {name} updated"); } @@ -192,17 +176,17 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult Delete(string name) { - string username = getUsername(); + string uploaderId = getUserId(); - if (username == null) + if (uploaderId == null) return BadRequest(); - var dataset = _datasetService.GetOneDataset(username, name); + var dataset = _datasetService.GetOneDataset(uploaderId, name); if (dataset == null) - return NotFound($"Dataset with name = {name} or user with username = {username} not found"); + return NotFound($"Dataset with name = {name} or user with ID = {uploaderId} not found"); - _datasetService.Delete(dataset.username, dataset.name); + _datasetService.Delete(dataset.uploaderId, dataset.name); return Ok($"Dataset with name = {name} deleted"); diff --git a/backend/api/api/Controllers/ModelController.cs b/backend/api/api/Controllers/ModelController.cs index 04c072da..fe16507b 100644 --- a/backend/api/api/Controllers/ModelController.cs +++ b/backend/api/api/Controllers/ModelController.cs @@ -56,23 +56,6 @@ namespace api.Controllers 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")] @@ -81,16 +64,16 @@ namespace api.Controllers string experimentId = trainModelObject.ExperimentId; string modelId = trainModelObject.ModelId; - string uploaderId = getUserId(); + string userId = getUserId(); - if (uploaderId == null) + if (userId == null) return BadRequest(); var experiment=_experimentService.Get(experimentId); var dataset = _datasetService.GetOneDataset(experiment.datasetId); - var filepath = _fileService.GetFilePath(dataset.fileId, uploaderId); + var filepath = _fileService.GetFilePath(dataset.fileId, userId); var model = _modelService.GetOneModel(modelId); - _mlService.TrainModel(model,experiment,filepath,dataset,uploaderId);//To do Obavestiti korisnika kada se model istrenira + _mlService.TrainModel(model,experiment,filepath,dataset, userId);//To do Obavestiti korisnika kada se model istrenira return Ok(); } @@ -99,7 +82,7 @@ namespace api.Controllers { var model=_modelService.GetOneModel(info.ModelId); - var user = _userService.GetUserByUsername(model.username); + var user = _userService.GetUserById(model.uploaderId); if (ChatHub.CheckUser(user._id)) await _ichat.Clients.Client(ChatHub.Users[user._id]).SendAsync("NotifyEpoch",model.name,info.ModelId,info.Stat,model.epochs,info.EpochNum); @@ -117,12 +100,12 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult<List<Model>> Get() { - string username = getUsername(); - - if (username == null) + string uploaderId = getUserId(); + + if (uploaderId == null) return BadRequest(); - return _modelService.GetMyModels(username); + return _modelService.GetMyModels(uploaderId); } // vraca svoj model prema nekom imenu @@ -131,12 +114,12 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult<Model> Get(string name) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); - var model = _modelService.GetOneModel(username, name); + var model = _modelService.GetOneModel(userId, name); if (model == null) return NotFound($"Model with name = {name} not found"); @@ -155,14 +138,14 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult<List<Model>> GetLatestModels(int latest) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); //ako bude trebao ID, samo iz baze uzeti - List<Model> lista = _modelService.GetLatestModels(username); + List<Model> lista = _modelService.GetLatestModels(userId); List<Model> novaLista = new List<Model>(); @@ -185,7 +168,7 @@ namespace api.Controllers /*if (_modelService.CheckHyperparameters(1, model.hiddenLayerNeurons, model.hiddenLayers, model.outputNeurons) == false) return BadRequest("Bad parameters!");*/ - var existingModel = _modelService.GetOneModel(model.username, model.name); + var existingModel = _modelService.GetOneModel(model.uploaderId, model.name); if (existingModel != null && !overwrite) return NotFound($"Model with name = {model.name} exisits"); @@ -209,18 +192,18 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult Put(string name, [FromBody] Model model) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); - var existingModel = _modelService.GetOneModel(username, name); + var existingModel = _modelService.GetOneModel(userId, name); if (existingModel == null) - return NotFound($"Model with name = {name} or user with username = {username} not found"); + return NotFound($"Model with name = {name} or user with ID = {userId} not found"); - _modelService.Update(username, name, model); + _modelService.Update(userId, name, model); return NoContent(); } @@ -229,17 +212,17 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult Delete(string name) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); - var model = _modelService.GetOneModel(username, name); + var model = _modelService.GetOneModel(userId, name); if (model == null) - return NotFound($"Model with name = {name} or user with username = {username} not found"); + return NotFound($"Model with name = {name} or user with ID = {userId} not found"); - _modelService.Delete(model.username, model.name); + _modelService.Delete(model.uploaderId, model.name); return Ok($"Model with name = {name} deleted"); diff --git a/backend/api/api/Controllers/PredictorController.cs b/backend/api/api/Controllers/PredictorController.cs index 64907dac..dd5aa5fd 100644 --- a/backend/api/api/Controllers/PredictorController.cs +++ b/backend/api/api/Controllers/PredictorController.cs @@ -32,22 +32,22 @@ namespace api.Controllers _modelService = modelService; } - public string getUsername() + public string getUserId() { - string username; + string uploaderId; 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) + uploaderId = jwtToken.TokenToId(parameter); + if (uploaderId == null) return null; } else return null; - return username; + return uploaderId; } // GET: api/<PredictorController>/mypredictors @@ -55,12 +55,12 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult<List<Predictor>> Get() { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); - return _predictorService.GetMyPredictors(username); + return _predictorService.GetMyPredictors(userId); } // GET: api/<PredictorController>/publicpredictors @@ -90,12 +90,12 @@ namespace api.Controllers [Authorize(Roles = "User,Guest")] public ActionResult<Predictor> GetPredictor(string id) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); - Predictor predictor = _predictorService.GetPredictor(username, id); + Predictor predictor = _predictorService.GetPredictor(userId, id); if (predictor == null) return NotFound($"Predictor with id = {id} not found"); @@ -108,11 +108,12 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult<Predictor> Get(string id) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); + //treba userId da se salje GetOnePredictor var predictor = _predictorService.GetOnePredictor(id); if (predictor == null) @@ -130,12 +131,12 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult<List<Predictor>> SortPredictors(bool ascdsc, int latest) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); - List<Predictor> lista = _predictorService.SortPredictors(username, ascdsc, latest); + List<Predictor> lista = _predictorService.SortPredictors(userId, ascdsc, latest); if(latest == 0) return lista; @@ -154,7 +155,7 @@ namespace api.Controllers [HttpPost("add")] public async Task<ActionResult<Predictor>> Post([FromBody] Predictor predictor) { - var user=_userService.GetUserByUsername(predictor.username); + var user=_userService.GetUserById(predictor.uploaderId); predictor.dateCreated = DateTime.Now.ToUniversalTime(); var model = _modelService.GetOneModel(predictor.modelId); if (model == null || user==null) @@ -171,12 +172,12 @@ namespace api.Controllers [Authorize(Roles = "User,Guest")] public async Task<ActionResult> UsePredictor(String id, [FromBody] PredictorColumns[] inputs) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); - Predictor predictor = _predictorService.GetPredictor(username, id); + Predictor predictor = _predictorService.GetPredictor(userId, id); Experiment e = _experimentService.Get(predictor.experimentId); @@ -195,16 +196,16 @@ namespace api.Controllers [Authorize(Roles = "User")] public ActionResult Put(string id, [FromBody] Predictor predictor) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); var existingPredictor = _predictorService.GetOnePredictor(id); //ne mora da se proverava if (existingPredictor == null) - return NotFound($"Predictor with id = {id} or user with username = {username} not found"); + return NotFound($"Predictor with id = {id} or user with ID = {userId} not found"); _predictorService.Update(id, predictor); @@ -212,21 +213,21 @@ namespace api.Controllers } // DELETE api/<PredictorController>/name - [HttpDelete("{name}")] + [HttpDelete("{id}")] [Authorize(Roles = "User")] public ActionResult Delete(string id) { - string username = getUsername(); + string userId = getUserId(); - if (username == null) + if (userId == null) return BadRequest(); var predictor = _predictorService.GetOnePredictor(id); if (predictor == null) - return NotFound($"Predictor with id = {id} or user with username = {username} not found"); + return NotFound($"Predictor with id = {id} or user with ID = {userId} not found"); - _predictorService.Delete(id); + _predictorService.Delete(id, userId); return Ok($"Predictor with id = {id} deleted"); diff --git a/backend/api/api/Models/Dataset.cs b/backend/api/api/Models/Dataset.cs index 47814449..cc7185f0 100644 --- a/backend/api/api/Models/Dataset.cs +++ b/backend/api/api/Models/Dataset.cs @@ -7,7 +7,7 @@ namespace api.Models public class Dataset { public Dataset() { } - public string username { get; set; } + public string uploaderId { get; set; } [BsonId] [BsonRepresentation(BsonType.ObjectId)]//mongo data type to .net diff --git a/backend/api/api/Models/Model.cs b/backend/api/api/Models/Model.cs index 72ee093b..a9dbfbdd 100644 --- a/backend/api/api/Models/Model.cs +++ b/backend/api/api/Models/Model.cs @@ -9,7 +9,7 @@ namespace api.Models [BsonId] [BsonRepresentation(BsonType.ObjectId)]//mongo data type to .net public string _id { get; set; } - public string username { get; set; } + public string uploaderId { get; set; } public string name { get; set; } diff --git a/backend/api/api/Models/Predictor.cs b/backend/api/api/Models/Predictor.cs index 26371d2a..8608d766 100644 --- a/backend/api/api/Models/Predictor.cs +++ b/backend/api/api/Models/Predictor.cs @@ -9,7 +9,7 @@ namespace api.Models [BsonId] [BsonRepresentation(BsonType.ObjectId)]//mongo data type to .net public string _id { get; set; } - public string username { get; set; } + public string uploaderId { get; set; } //public string name { get; set; } //public string description { get; set; } public string[] inputs { get; set; } diff --git a/backend/api/api/Services/DatasetService.cs b/backend/api/api/Services/DatasetService.cs index 176ab424..f260a1ba 100644 --- a/backend/api/api/Services/DatasetService.cs +++ b/backend/api/api/Services/DatasetService.cs @@ -14,7 +14,7 @@ namespace api.Services _dataset = database.GetCollection<Dataset>(settings.DatasetCollectionName); } - public List<Dataset> SearchDatasets(string name, string username) + public List<Dataset> SearchDatasets(string name) { return _dataset.Find(dataset => dataset.name == name && dataset.isPublic == true && dataset.isPreProcess).ToList(); } @@ -27,27 +27,27 @@ namespace api.Services } //brisanje odredjenog name-a - public void Delete(string username, string name) + public void Delete(string userId, string id) { - _dataset.DeleteOne(dataset => (dataset.username == username && dataset.name == name)); + _dataset.DeleteOne(dataset => (dataset.uploaderId == userId && dataset._id == id)); } - public List<Dataset> GetMyDatasets(string username) + public List<Dataset> GetMyDatasets(string userId) { - return _dataset.Find(dataset => dataset.username == username && dataset.isPreProcess).ToList(); + return _dataset.Find(dataset => dataset.uploaderId == userId && dataset.isPreProcess).ToList(); } public List<Dataset> GetGuestDatasets() { //Join Igranonica public datasetove sa svim temp uploadanim datasetovima - List<Dataset> datasets= _dataset.Find(dataset => dataset.username == "Igrannonica" && dataset.isPublic == true && dataset.isPreProcess).ToList(); - datasets.AddRange(_dataset.Find(dataset => dataset.username == "" && dataset.isPreProcess).ToList()); + List<Dataset> datasets= _dataset.Find(dataset => dataset.uploaderId == "Igrannonica" && dataset.isPublic == true && dataset.isPreProcess).ToList(); + datasets.AddRange(_dataset.Find(dataset => dataset.uploaderId == "" && dataset.isPreProcess).ToList()); return datasets; } //poslednji datasetovi - public List<Dataset> SortDatasets(string username, bool ascdsc, int latest) + public List<Dataset> SortDatasets(string userId, bool ascdsc, int latest) { - List<Dataset> list = _dataset.Find(dataset => dataset.username == username && dataset.isPreProcess).ToList(); + List<Dataset> list = _dataset.Find(dataset => dataset.uploaderId == userId && dataset.isPreProcess).ToList(); if(ascdsc) list = list.OrderBy(dataset => dataset.lastUpdated).ToList(); @@ -62,9 +62,9 @@ namespace api.Services return _dataset.Find(dataset => dataset.isPublic == true && dataset.isPreProcess).ToList(); } - public Dataset GetOneDataset(string username, string name) + public Dataset GetOneDataset(string userId, string name) { - return _dataset.Find(dataset => dataset.username == username && dataset.name == name && dataset.isPreProcess).FirstOrDefault(); + return _dataset.Find(dataset => dataset.uploaderId == userId && dataset.name == name && dataset.isPreProcess).FirstOrDefault(); } //odraditi za pretragu getOne @@ -74,9 +74,9 @@ namespace api.Services } //ako je potrebno da se zameni name ili ekstenzija - public void Update(string username, string name, Dataset dataset ) + public void Update(string userId, string id, Dataset dataset ) { - _dataset.ReplaceOne(dataset => dataset.username == username && dataset.name == name, dataset); + _dataset.ReplaceOne(dataset => dataset.uploaderId == userId && dataset._id == id, dataset); } public void Update(Dataset dataset) { @@ -85,7 +85,7 @@ namespace api.Services public string GetDatasetId(string fileId) { - Dataset dataset = _dataset.Find(dataset => dataset.fileId == fileId && dataset.username == "Igrannonica").FirstOrDefault(); + Dataset dataset = _dataset.Find(dataset => dataset.fileId == fileId && dataset.uploaderId == "Igrannonica").FirstOrDefault(); return dataset._id; } diff --git a/backend/api/api/Services/IDatasetService.cs b/backend/api/api/Services/IDatasetService.cs index c6138943..f493a2ec 100644 --- a/backend/api/api/Services/IDatasetService.cs +++ b/backend/api/api/Services/IDatasetService.cs @@ -5,15 +5,15 @@ namespace api.Services { public interface IDatasetService { - Dataset GetOneDataset(string username, string name); + Dataset GetOneDataset(string userId, string name); Dataset GetOneDataset(string id); - List<Dataset> SearchDatasets(string name, string username); - List<Dataset> GetMyDatasets(string username); - List<Dataset> SortDatasets(string username, bool ascdsc, int latest); + List<Dataset> SearchDatasets(string name); + List<Dataset> GetMyDatasets(string userId); + List<Dataset> SortDatasets(string userId, bool ascdsc, int latest); List<Dataset> GetPublicDatasets(); Dataset Create(Dataset dataset); - void Update(string username, string name, Dataset dataset); - void Delete(string username, string name); + void Update(string userId, string id, Dataset dataset); + void Delete(string userId, string id); public List<Dataset> GetGuestDatasets(); public void Update(Dataset dataset); string GetDatasetId(string fileId); diff --git a/backend/api/api/Services/IModelService.cs b/backend/api/api/Services/IModelService.cs index e10b8f3b..bcb82e2d 100644 --- a/backend/api/api/Services/IModelService.cs +++ b/backend/api/api/Services/IModelService.cs @@ -5,16 +5,16 @@ namespace api.Services { public interface IModelService { - Model GetOneModel(string username, string name); + Model GetOneModel(string userId, string name); Model GetOneModel(string id); - List<Model> GetMyModels(string username); - List<Model> GetLatestModels(string username); + List<Model> GetMyModels(string userId); + List<Model> GetLatestModels(string userId); //List<Model> GetPublicModels(); Model Create(Model model); Model Replace(Model model); - void Update(string username, string name, Model model); + void Update(string userId, string name, Model model); public void Update(string id, Model model); - void Delete(string username, string name); + void Delete(string userId, string name); bool CheckHyperparameters(int inputNeurons, int hiddenLayerNeurons, int hiddenLayers, int outputNeurons); bool CheckDb(); } diff --git a/backend/api/api/Services/IPredictorService.cs b/backend/api/api/Services/IPredictorService.cs index 7c31215e..16f0432a 100644 --- a/backend/api/api/Services/IPredictorService.cs +++ b/backend/api/api/Services/IPredictorService.cs @@ -5,12 +5,12 @@ namespace api.Services public interface IPredictorService { Predictor Create(Predictor predictor); - void Delete(string id); - List<Predictor> GetMyPredictors(string username); + void Delete(string id, string userId); + List<Predictor> GetMyPredictors(string userId); Predictor GetOnePredictor(string id); - Predictor GetPredictor(string username, string id); + Predictor GetPredictor(string userId, string id); List<Predictor> GetPublicPredictors(); - List<Predictor> SortPredictors(string username, bool ascdsc, int latest); + List<Predictor> SortPredictors(string userId, bool ascdsc, int latest); void Update(string id, Predictor predictor); } }
\ No newline at end of file diff --git a/backend/api/api/Services/MlConnectionService.cs b/backend/api/api/Services/MlConnectionService.cs index 22db0aea..17c0f8b8 100644 --- a/backend/api/api/Services/MlConnectionService.cs +++ b/backend/api/api/Services/MlConnectionService.cs @@ -67,7 +67,7 @@ namespace api.Services public async Task<string> Predict(Predictor predictor, Experiment experiment, PredictorColumns[] inputs) { - string filePath = _fileService.GetFilePath(predictor.h5FileId, predictor.username); + string filePath = _fileService.GetFilePath(predictor.h5FileId, predictor.uploaderId); var request = new RestRequest("predict", Method.Post); request.AddParameter("predictor", JsonConvert.SerializeObject(predictor)); diff --git a/backend/api/api/Services/ModelService.cs b/backend/api/api/Services/ModelService.cs index c21844f7..d3ff9bf9 100644 --- a/backend/api/api/Services/ModelService.cs +++ b/backend/api/api/Services/ModelService.cs @@ -26,18 +26,18 @@ namespace api.Services return model; } - public void Delete(string username, string name) + public void Delete(string userId, string name) { - _model.DeleteOne(model => (model.username == username && model.name == name)); + _model.DeleteOne(model => (model.uploaderId == userId && model.name == name)); } - public List<Model> GetMyModels(string username) + public List<Model> GetMyModels(string userId) { - return _model.Find(model => model.username == username).ToList(); + return _model.Find(model => model.uploaderId == userId).ToList(); } - public List<Model> GetLatestModels(string username) + public List<Model> GetLatestModels(string userId) { - List<Model> list = _model.Find(model => model.username == username).ToList(); + List<Model> list = _model.Find(model => model.uploaderId == userId).ToList(); list = list.OrderByDescending(model => model.lastUpdated).ToList(); @@ -50,9 +50,9 @@ namespace api.Services return _model.Find(model => model.isPublic == true).ToList(); } */ - public Model GetOneModel(string username, string name) + public Model GetOneModel(string userId, string name) { - return _model.Find(model => model.username == username && model.name == name).FirstOrDefault(); + return _model.Find(model => model.uploaderId == userId && model.name == name).FirstOrDefault(); } public Model GetOneModel(string id) @@ -60,9 +60,9 @@ namespace api.Services return _model.Find(model => model._id == id).FirstOrDefault(); } - public void Update(string username, string name, Model model) + public void Update(string userId, string name, Model model) { - _model.ReplaceOne(model => model.username == username && model.name == name, model); + _model.ReplaceOne(model => model.uploaderId == userId && model.name == name, model); } public void Update(string id, Model model) { @@ -83,7 +83,7 @@ namespace api.Services public bool CheckDb() { Model? model = null; - model = _model.Find(model => model.username == "igrannonica").FirstOrDefault(); + model = _model.Find(model => model.uploaderId == "Igrannonica").FirstOrDefault(); if (model != null) return false; diff --git a/backend/api/api/Services/PredictorService.cs b/backend/api/api/Services/PredictorService.cs index 144248d4..756cc943 100644 --- a/backend/api/api/Services/PredictorService.cs +++ b/backend/api/api/Services/PredictorService.cs @@ -21,14 +21,14 @@ namespace api.Services return predictor; } - public void Delete(string id) + public void Delete(string id, string userId) { - _predictor.DeleteOne(predictor => (predictor._id == id)); + _predictor.DeleteOne(predictor => (predictor._id == id && predictor.uploaderId == userId)); } - public List<Predictor> GetMyPredictors(string username) + public List<Predictor> GetMyPredictors(string userId) { - return _predictor.Find(predictor => predictor.username == username).ToList(); + return _predictor.Find(predictor => predictor.uploaderId == userId).ToList(); } public Predictor GetOnePredictor(string id) @@ -36,15 +36,15 @@ namespace api.Services return _predictor.Find(predictor => predictor._id == id).FirstOrDefault(); } - public Predictor GetPredictor(string username, string id) + public Predictor GetPredictor(string userId, string id) { - return _predictor.Find(predictor => predictor._id == id && (predictor.username == username || predictor.isPublic == true)).FirstOrDefault(); + return _predictor.Find(predictor => predictor._id == id && (predictor.uploaderId == userId || predictor.isPublic == true)).FirstOrDefault(); } - public List<Predictor> SortPredictors(string username, bool ascdsc, int latest) + public List<Predictor> SortPredictors(string userId, bool ascdsc, int latest) { - List<Predictor> list = _predictor.Find(predictor => predictor.username == username).ToList(); + List<Predictor> list = _predictor.Find(predictor => predictor.uploaderId == userId).ToList(); if (ascdsc) list = list.OrderBy(predictor => predictor.dateCreated).ToList(); diff --git a/backend/api/api/Services/TempRemovalService.cs b/backend/api/api/Services/TempRemovalService.cs index e7f366a3..302ca974 100644 --- a/backend/api/api/Services/TempRemovalService.cs +++ b/backend/api/api/Services/TempRemovalService.cs @@ -27,7 +27,7 @@ namespace api.Services if ((DateTime.Now.ToUniversalTime() - file.date).TotalDays >= 1) { DeleteFile(file._id); - List<Dataset> datasets = _dataset.Find(dataset => dataset.fileId == file._id && dataset.username=="").ToList(); + List<Dataset> datasets = _dataset.Find(dataset => dataset.fileId == file._id && dataset.uploaderId=="").ToList(); foreach(var dataset in datasets) { DeleteDataset(dataset._id); @@ -37,7 +37,7 @@ namespace api.Services DeleteExperiment(experiment._id); foreach(var modelId in experiment.ModelIds) { - var delModel=_model.Find(model=> modelId== model._id && model.username=="").FirstOrDefault(); + var delModel=_model.Find(model=> modelId== model._id && model.uploaderId=="").FirstOrDefault(); if(delModel!= null) DeleteModel(delModel._id); } @@ -48,7 +48,7 @@ namespace api.Services } } //Brisanje modela ukoliko gost koristi vec postojeci dataset - List<Model> models1= _model.Find(model =>model.username == "").ToList(); + List<Model> models1= _model.Find(model =>model.uploaderId == "").ToList(); foreach(var model in models1) { if ((DateTime.Now.ToUniversalTime() - model.dateCreated.ToUniversalTime()).TotalDays >= 1) diff --git a/backend/api/api/Services/UserService.cs b/backend/api/api/Services/UserService.cs index 7fc4bdb1..b53f5fdc 100644 --- a/backend/api/api/Services/UserService.cs +++ b/backend/api/api/Services/UserService.cs @@ -51,17 +51,17 @@ namespace api.Services using (var session = _client.StartSession()) { if(username!=user.Username) - if(_users.Find(u => u.Username == user.Username).FirstOrDefault()!=null) - { - return false; - } + if(_users.Find(u => u.Username == user.Username).FirstOrDefault()!=null) + { + return false; + } //Trenutan MongoDB Server ne podrzava transakcije.Omoguciti Podrsku //session.StartTransaction(); try { _users.ReplaceOne(user => user.Username == username, user); - if (username != user.Username) + /*if (username != user.Username) { var builderModel = Builders<Model>.Update; var builderDataset = Builders<Dataset>.Update; @@ -70,7 +70,7 @@ namespace api.Services _datasets.UpdateMany(x => x.username == username, builderDataset.Set(x => x.username, user.Username)); _predictors.UpdateMany(x => x.username == username, builderPredictor.Set(x => x.username, user.Username)); } - + */ //session.AbortTransaction(); diff --git a/backend/microservice/api/controller.py b/backend/microservice/api/controller.py index e6515e7b..9b83b8e7 100644 --- a/backend/microservice/api/controller.py +++ b/backend/microservice/api/controller.py @@ -78,7 +78,7 @@ def train(): m.append({"Name" : attribute, "JsonValue" : value}) predictor = { "_id" : "", - "username" : paramsModel["username"], + "uploaderId" : paramsModel["uploaderId"], "inputs" : paramsExperiment["inputColumns"], "output" : paramsExperiment["outputColumn"], "isPublic" : False, diff --git a/backend/microservice/api/newmlservice.py b/backend/microservice/api/newmlservice.py index a9bce3bb..9951c25f 100644 --- a/backend/microservice/api/newmlservice.py +++ b/backend/microservice/api/newmlservice.py @@ -156,48 +156,53 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): # ### Enkodiranje encoding=paramsExperiment["encoding"] - if(encoding=='label'): - encoder=LabelEncoder() - for col in data.columns: - if(data[col].dtype==np.object_): - data[col]=encoder.fit_transform(data[col]) + datafront=dataset.copy() + svekolone=datafront.columns + kategorijskekolone=datafront.select_dtypes(include=['object']).columns + for kolona in svekolone: + if(kolona in kategorijskekolone): + if(encoding=='label'): + encoder=LabelEncoder() + for col in data.columns: + if(data[col].dtype==np.object_): + data[col]=encoder.fit_transform(data[col]) - elif(encoding=='onehot'): - category_columns=[] - for col in data.columns: - if(data[col].dtype==np.object_): - category_columns.append(col) - data=pd.get_dummies(data, 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]) - - elif(encoding=='hashing'): - category_columns=[] - for col in data.columns: - if(data[col].dtype==np.object_): - category_columns.append(col) - encoder=ce.HashingEncoder(cols=category_columns, n_components=len(category_columns)) - encoder.fit_transform(data) - elif(encoding=='binary'): - category_columns=[] - for col in data.columns: - if(data[col].dtype==np.object_): - category_columns.append(col) - encoder=ce.BinaryEncoder(cols=category_columns, return_df=True) - encoder.fit_transform(data) - - elif(encoding=='baseN'): - category_columns=[] - for col in data.columns: - if(data[col].dtype==np.object_): - category_columns.append(col) - encoder=ce.BaseNEncoder(cols=category_columns, return_df=True, base=5) - encoder.fit_transform(data) + elif(encoding=='onehot'): + category_columns=[] + for col in data.columns: + if(data[col].dtype==np.object_): + category_columns.append(col) + data=pd.get_dummies(data, 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]) + + elif(encoding=='hashing'): + category_columns=[] + for col in data.columns: + if(data[col].dtype==np.object_): + category_columns.append(col) + encoder=ce.HashingEncoder(cols=category_columns, n_components=len(category_columns)) + encoder.fit_transform(data) + elif(encoding=='binary'): + category_columns=[] + for col in data.columns: + if(data[col].dtype==np.object_): + category_columns.append(col) + encoder=ce.BinaryEncoder(cols=category_columns, return_df=True) + encoder.fit_transform(data) + + elif(encoding=='baseN'): + category_columns=[] + for col in data.columns: + if(data[col].dtype==np.object_): + category_columns.append(col) + encoder=ce.BaseNEncoder(cols=category_columns, return_df=True, base=5) + encoder.fit_transform(data) # # Input - output # diff --git a/frontend/src/app/_data/Dataset.ts b/frontend/src/app/_data/Dataset.ts index 732d1c56..766040a3 100644 --- a/frontend/src/app/_data/Dataset.ts +++ b/frontend/src/app/_data/Dataset.ts @@ -10,7 +10,7 @@ export default class Dataset { public accessibleByLink: boolean = false, public dateCreated: Date = new Date(), public lastUpdated: Date = new Date(), - public username: string = '', + public uploaderId: string = '', public delimiter: string = '', public hasHeader: boolean = true, diff --git a/frontend/src/app/_data/Experiment.ts b/frontend/src/app/_data/Experiment.ts index 453f6ca0..95ef6e1e 100644 --- a/frontend/src/app/_data/Experiment.ts +++ b/frontend/src/app/_data/Experiment.ts @@ -1,3 +1,4 @@ +import { ProblemType } from "./Model"; export default class Experiment { _id: string = ''; uploaderId: string = ''; @@ -18,8 +19,8 @@ export default class Experiment { 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 + public encodings: ColumnEncoding[] = [], + public type: ProblemType = ProblemType.Regression ) { } } @@ -65,4 +66,12 @@ export enum Encoding { WOE = 'woe', Quantile = 'quantile' */ +} + +export class ColumnEncoding { + constructor ( + public columnName: string, + public encoding: Encoding + ) + {} }
\ No newline at end of file diff --git a/frontend/src/app/_data/Model.ts b/frontend/src/app/_data/Model.ts index 1af3fe30..b273f56a 100644 --- a/frontend/src/app/_data/Model.ts +++ b/frontend/src/app/_data/Model.ts @@ -19,7 +19,7 @@ export default class Model { public batchSize: number = 5, public hiddenLayerActivationFunctions: string[] = ['sigmoid'], public outputLayerActivationFunction: ActivationFunction = ActivationFunction.Sigmoid, - public username: string = '', + public uploaderId: string = '', public metrics: string[] = [], // TODO add to add-model form public epochs: number = 5 // TODO add to add-model form ) { } diff --git a/frontend/src/app/_data/Notification.ts b/frontend/src/app/_data/Notification.ts index c505d399..94a3be1d 100644 --- a/frontend/src/app/_data/Notification.ts +++ b/frontend/src/app/_data/Notification.ts @@ -1,5 +1,4 @@ export default class Notification { - _id: string = ''; constructor( public title: string = 'Treniranje u toku...', public id: string = '042', diff --git a/frontend/src/app/_data/Predictor.ts b/frontend/src/app/_data/Predictor.ts index 7e902eae..8aa2b6cb 100644 --- a/frontend/src/app/_data/Predictor.ts +++ b/frontend/src/app/_data/Predictor.ts @@ -7,6 +7,7 @@ export default class Predictor { public output: string = '', public isPublic: boolean = false, public accessibleByLink: boolean = false, - public dateCreated: Date = new Date() + public dateCreated: Date = new Date(), + public uploaderId: string = '' ) { } }
\ No newline at end of file diff --git a/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.ts b/frontend/src/app/_elements/add-new-dataset/add-new-dataset.component.ts index 6ff108ce..3e1b5c73 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 @@ -90,7 +90,7 @@ 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.dataset.uploaderId = shared.userId; this.datasetsService.addDataset(this.dataset).subscribe((dataset) => { this.newDatasetAdded.emit("added"); 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 62cca456..73dbf2d2 100644 --- a/frontend/src/app/_elements/dataset-load/dataset-load.component.ts +++ b/frontend/src/app/_elements/dataset-load/dataset-load.component.ts @@ -41,12 +41,14 @@ export class DatasetLoadComponent implements OnInit { viewMyDatasetsForm() { this.showMyDatasets = true; - this.resetSelectedDataset(); + if (this.selectedDataset != undefined) + this.resetSelectedDataset(); //this.resetCbsAndRbs(); //TREBA DA SE DESI } viewNewDatasetForm() { this.showMyDatasets = false; - this.resetSelectedDataset(); + if (this.selectedDataset != undefined) + this.resetSelectedDataset(); //this.resetCbsAndRbs(); //TREBA DA SE DESI } diff --git a/frontend/src/app/_elements/item-predictor/item-predictor.component.html b/frontend/src/app/_elements/item-predictor/item-predictor.component.html index 7ae26fd3..3199dcc8 100644 --- a/frontend/src/app/_elements/item-predictor/item-predictor.component.html +++ b/frontend/src/app/_elements/item-predictor/item-predictor.component.html @@ -1,26 +1,35 @@ <div class="card" style="min-width: 12rem;"> - <div class="card-header"> - {{predictor.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;">Prediktor</b></div> + </div> - <div class="card-body"> + <div class="card-body overflow-hidden"> + <b style="color: gray;">Opis</b><hr style="width: 20%;"> <p class="card-text"> - {{predictor.description}} + {{predictor.description}} </p> - <div class="d-flex flex-column align-items-center"> - <table class="table table-bordered table-sm"> + + <b style="color: gray;">Ulazne kolone</b> + <div style="overflow: scroll; overflow-y: hidden;"> + + <table class="table table-bordered table-md" > <thead> - <th class="text-center" *ngFor="let column of predictor.inputs">{{column}}</th> + <th scope="col" *ngFor="let column of predictor.inputs" >{{column}}</th> </thead> </table> - <mat-icon>arrow_downward</mat-icon> - <p> - {{predictor.output}} - </p> + </div> + <b style="color: gray;">Izlazna kolona: </b><b>{{predictor.output}}</b> + <hr> + <div> + <table> + <tr><td><span class="material-icons">calendar_today</span></td><td><span style="color: grey;"> <b> Kreirano</b></span></td><td>{{predictor.dateCreated |date}}</td></tr> + </table> </div> </div> <div class="card-footer text-center"> - <button class="btn btn-lg col-4" style="background-color:#003459; color:white;" + <button class="btn btn-md col-4" style="background-color:#003459; color:white;" (click)="openPredictor();">Iskoristi</button> - <!--<a routerLink="/predict" mat-raised-button color="primary">Iskoristi</a>--> + </div> </div>
\ No newline at end of file diff --git a/frontend/src/app/_elements/model-load/model-load.component.html b/frontend/src/app/_elements/model-load/model-load.component.html index f40ea476..dcb35c21 100644 --- a/frontend/src/app/_elements/model-load/model-load.component.html +++ b/frontend/src/app/_elements/model-load/model-load.component.html @@ -17,7 +17,7 @@ <div *ngIf="showMyModels" class="px-5"> <div class="overflow-auto" style="max-height: 500px;"> <ul class="list-group"> - <li class="list-group-item p-3" *ngFor="let model of myModels|filter:term" + <li class="list-group-item p-3" *ngFor="let model of myModels|filter:term|filter:(forExperiment ? forExperiment.type : '')" [ngClass]="{'selectedModelClass': this.selectedModel == model}"> <app-item-model name="usersModel" [model]="model" (click)="selectThisModel(model);"> </app-item-model> @@ -43,11 +43,7 @@ <textarea class="form-control" name="desc" rows="3" [(ngModel)]="newModel.description"></textarea> </div> </div> - <div class="col-2"> - <label for="dateCreated" class="col-form-label">Datum:</label> - <input type="text" class="form-control-plaintext" id="dateCreated" placeholder="--/--/--" - value="{{newModel.dateCreated | date: 'dd/MM/yyyy'}}" readonly> - </div> + </div> <h2 class="mt-5 mb-4 mx-5">Parametri treniranja modela:</h2> <div> @@ -58,7 +54,7 @@ <label for="type" class="col-form-label">Tip problema: </label> </div> <div class="col-2"> - <select id=typeOptions class="form-control" name="type" [(ngModel)]="newModel.type" + <select id=typeOptions class="form-select" name="type" [(ngModel)]="newModel.type" (change)="filterOptions()"> <option *ngFor="let option of Object.keys(ProblemType); let optionName of Object.values(ProblemType)" @@ -86,7 +82,7 @@ <label for="optimizer" class="col-form-label">Optimizacija: </label> </div> <div class="col-2"> - <select id=optimizerOptions class="form-control" name="optimizer" [(ngModel)]="newModel.optimizer"> + <select id=optimizerOptions class="form-select" name="optimizer" [(ngModel)]="newModel.optimizer"> <option *ngFor="let option of Object.keys(Optimizer); let optionName of Object.values(Optimizer)" [value]="option"> @@ -108,10 +104,10 @@ <div class="row p-2"> <div class="col-1"></div> <div class="col-3"> - <label for="lossFunction" class="col-form-label">Funkcija obrade gubitka: </label> + <label for="lossFunction" class="col-form-label">Funkcija troška: </label> </div> <div class="col-2"> - <select id=lossFunctionOptions class="form-control" name="lossFunction" + <select id=lossFunctionOptions class="form-select" name="lossFunction" [(ngModel)]="newModel.lossFunction" aria-checked="true"> <option *ngFor="let option of Object.keys(lossFunction); let optionName of Object.values(lossFunction)" @@ -125,7 +121,21 @@ <label for="batchSize" class="col-form-label">Broj uzorka po iteraciji: </label> </div> <div class="col-1"> - <input type="number" min="1" class="form-control" name="batchSize" [(ngModel)]="newModel.batchSize"> + + <input type="number" min="0" step="1" max="7" class="form-control" name="batchSizePower" [(ngModel)]="batchSizePower" (click)="updateBatchSize()" > + {{newModel.batchSize}} + + </div> + + <div class="row p-2"> + <div class="col-1"></div> + <div class="col-3 m-1"> + <label for="epochs" class="col-form-label">Broj epoha: </label> + </div> + <div class="col-1"> + <input type="number" min="1" max="1000" class="form-control" name="epochs" + [(ngModel)]="newModel.epochs"> + </div> </div> </div> @@ -147,8 +157,8 @@ <div class="input-group-prepend"> <span class="input-group-text">#{{i+1}}</span> </div> - <select [id]="'hiddenLayerActivationFunctionOption_'+i" class="form-control" - [(ngModel)]="newModel.hiddenLayerActivationFunctions[i]"> + <select [id]="'hiddenLayerActivationFunctionOption_'+i" class="form-select" + [(ngModel)]="newModel.hiddenLayerActivationFunctions[i]" > <option *ngFor="let option of Object.keys(ActivationFunction); let optionName of Object.values(ActivationFunction)" [value]="option"> @@ -164,7 +174,7 @@ style="text-align: center;">Funkcija aktivacije<br>izlaznog sloja:</label> </div> <div class="col-2 mt-2"> - <select id=outputLayerActivationFunctionOptions class="form-control" + <select id=outputLayerActivationFunctionOptions class="form-select" name="outputLayerActivationFunction" [(ngModel)]="newModel.outputLayerActivationFunction"> <option *ngFor="let option of Object.keys(ActivationFunction); let optionName of Object.values(ActivationFunction)" 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 745dc12e..dbca3d17 100644 --- a/frontend/src/app/_elements/model-load/model-load.component.ts +++ b/frontend/src/app/_elements/model-load/model-load.component.ts @@ -1,5 +1,6 @@ -import { Component, OnInit, ViewChild, Output, EventEmitter } from '@angular/core'; +import { Component, OnInit, ViewChild, Output, EventEmitter, Input } from '@angular/core'; import Shared from 'src/app/Shared'; +import Experiment from 'src/app/_data/Experiment'; 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'; @@ -13,6 +14,7 @@ import { GraphComponent } from '../graph/graph.component'; export class ModelLoadComponent implements OnInit { @ViewChild(GraphComponent) graph!: GraphComponent; + @Input() forExperiment?:Experiment; @Output() selectedModelChangeEvent = new EventEmitter<Model>(); newModel: Model = new Model(); @@ -43,6 +45,11 @@ export class ModelLoadComponent implements OnInit { ngOnInit(): void { } + batchSizePower:number=1; + updateBatchSize() + { + this.newModel.batchSize=2**this.batchSizePower; + } updateGraph() { this.graph.update(); @@ -62,7 +69,7 @@ export class ModelLoadComponent implements OnInit { uploadModel() { this.getMetrics(); - this.newModel.username = Shared.username; + this.newModel.uploaderId = Shared.userId; this.modelsService.addModel(this.newModel).subscribe((response) => { Shared.openDialog('Model dodat', 'Model je uspešno dodat u bazu.'); diff --git a/frontend/src/app/_elements/notifications/notifications.component.html b/frontend/src/app/_elements/notifications/notifications.component.html index ef897cfc..3b2f4eaa 100644 --- a/frontend/src/app/_elements/notifications/notifications.component.html +++ b/frontend/src/app/_elements/notifications/notifications.component.html @@ -11,14 +11,18 @@ </button> </h2> - <div id="collapseNotifs" class="collapse show"> + <div id="collapseNotifs" class="collapse show overflow-auto" style="max-height: 32rem;"> <div *ngFor="let notification of notifications" class="p-2 m-1 border rounded"> - <div class="d-flex flex-row"> - <p>{{notification.title}}</p> - </div> - <div *ngIf="notification.hasProgress" class="border-3 border-primary bg-dark m-1" style="height: 5px; margin-top: -10px !important;"> - <div class="bg-primary" style="height: 5px;" [style]="'width: '+(notification.progress*100)+'%;'"> + <div class="d-flex flex-row "> + <div> + <p>{{notification.title}}</p> + <div *ngIf="notification.hasProgress" class="border-3 border-primary bg-dark m-1" style="height: 5px; margin-top: -10px !important; min-width: 12rem;"> + <div class="bg-primary" style="height: 5px;" [style]="'width: '+(notification.progress*100)+'%;'"> + </div> + </div> </div> + <button type="button" class="btn-close ms-auto align-self-center" aria-label="Close" (click)="removeNotification(notification);"></button> </div> + </div> </div>
\ No newline at end of file diff --git a/frontend/src/app/_elements/notifications/notifications.component.ts b/frontend/src/app/_elements/notifications/notifications.component.ts index e199f70a..9b460240 100644 --- a/frontend/src/app/_elements/notifications/notifications.component.ts +++ b/frontend/src/app/_elements/notifications/notifications.component.ts @@ -21,13 +21,33 @@ export class NotificationsComponent implements OnInit { this.notifications.push(new Notification(`Obrađen izvor podataka: ${dName}`, dId, 1.0, false)); }); - this.signalRService.hubConnection.on("NotifyEpoch", (epoch: string, mName: string, mId: string, numEpochs) => { - //todo epoch - this.notifications.push(new Notification(`Treniranje modela: ${mName}`, mId, 0.5)); + this.signalRService.hubConnection.on("NotifyEpoch", (mName: string, mId: string, stat: string, totalEpochs: number, currentEpoch: number) => { + const existingNotification = this.notifications.find(x => x.id === mId) + const progress = ((currentEpoch + 1) / totalEpochs); + console.log("Ukupno epoha", totalEpochs, "Trenutna epoha:", currentEpoch); + if (!existingNotification) + this.notifications.push(new Notification(`Treniranje modela: ${mName}`, mId, progress, true)); + else { + existingNotification.progress = progress; + } + }); + + this.signalRService.hubConnection.on("NotifyModel", (mName: string, mId: string, stat: string, totalEpochs: number, currentEpoch: number) => { + const existingNotification = this.notifications.find(x => x.id === mId) + const progress = ((currentEpoch + 1) / totalEpochs); + if (!existingNotification) + this.notifications.push(new Notification(`Treniranje modela: ${mName}`, mId, progress, true)); + else { + existingNotification.progress = progress; + } }); } else { console.warn("Notifications: No connection!"); } } + removeNotification(notification: Notification) { + this.notifications.splice(this.notifications.indexOf(notification), 1); + } + } diff --git a/frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts b/frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts index c83bf208..66b3755e 100644 --- a/frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts +++ b/frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts @@ -33,7 +33,7 @@ export class FilterDatasetsComponent implements OnInit { newDataset._id = ""; newDataset.isPublic = false; newDataset.lastUpdated = new Date(); - newDataset.username = decodedToken.name; + newDataset.uploaderId = decodedToken.uploaderId; let name=prompt("Unesite naziv dataset-a",newDataset.name); newDataset.name=name as string; if(name!=null && name!="") 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 b0e9c4ef..9b281239 100644 --- a/frontend/src/app/_pages/my-models/my-models.component.html +++ b/frontend/src/app/_pages/my-models/my-models.component.html @@ -15,7 +15,7 @@ <div class="panel-footer row"><!-- panel-footer --> <div class="col-xs-6 text-center"> <div> - <button type="button" class="btn btn-default btn-lg"style="min-width: 7rem;float: left;" (click)="deleteThisModel(model)" mat-raised-button color="primary">Koristi + <button type="button" class="btn btn-default btn-lg"style="min-width: 7rem;float: left;" (click)="useThisModel(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> 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 92d3fbaa..d379fa69 100644 --- a/frontend/src/app/_pages/my-models/my-models.component.ts +++ b/frontend/src/app/_pages/my-models/my-models.component.ts @@ -1,4 +1,5 @@ import { Component, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; import shared from 'src/app/Shared'; import Model from 'src/app/_data/Model'; import { ModelsService } from 'src/app/_services/models.service'; @@ -12,7 +13,7 @@ export class MyModelsComponent implements OnInit { myModels: Model[] = []; //myModel: Model; - constructor(private modelsS : ModelsService) { + constructor(private modelsS : ModelsService, private router : Router) { @@ -44,6 +45,11 @@ deleteThisModel(model: Model): void{ } +useThisModel(model: Model): void{ + + this.router.navigate(['/training']) + +} getAllMyModels(): void{ this.modelsS.getMyModels().subscribe(m => { this.myModels = 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 d38f93e4..31fa786c 100644 --- a/frontend/src/app/_pages/my-predictors/my-predictors.component.html +++ b/frontend/src/app/_pages/my-predictors/my-predictors.component.html @@ -1,16 +1,23 @@ <div id="header"> <h1>Trenirani modeli</h1> </div> -<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> - </div> - <div> - <button (click)="delete(predictor)" mat-raised-button color="warn" style="min-width: 15rem;float: right" ><mat-icon>delete</mat-icon></button> - </div> - +<div id="wrapper"> +<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;"> + </div> + <div class="row"> + <div class="col-sm-4" style="margin-bottom: 10px;" *ngFor="let predictor of predictors"> + <app-item-predictor [predictor]="predictor"></app-item-predictor> + <div> + <button (click)="deleteThisPredictor(predictor)" mat-raised-button color="warn" style="min-width: 10rem;float: right" ><mat-icon>delete</mat-icon></button> + </div> + </div> + </div> +</div> </div> - </div> + + diff --git a/frontend/src/app/_pages/my-predictors/my-predictors.component.ts b/frontend/src/app/_pages/my-predictors/my-predictors.component.ts index 17c496fd..4dc5300d 100644 --- a/frontend/src/app/_pages/my-predictors/my-predictors.component.ts +++ b/frontend/src/app/_pages/my-predictors/my-predictors.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import Predictor from 'src/app/_data/Predictor'; import { PredictorsService } from 'src/app/_services/predictors.service'; - +import shared from 'src/app/Shared'; @Component({ selector: 'app-my-predictors', templateUrl: './my-predictors.component.html', @@ -12,28 +12,30 @@ export class MyPredictorsComponent implements OnInit { constructor(private predictorsS : PredictorsService) { } ngOnInit(): void { - this.getAllMyPredictors(); - + this.predictorsS.getMyPredictors().subscribe((response) => { + this.predictors = response; + }, (error) => { + if (error.error == "Predictor with...") { + shared.openDialog("Greska", "Greska"); + } + }); } - delete(predictor: Predictor){ - if(window.confirm("IZABRANI MODEL ĆE BITI IZBRISAN")) - { - this.predictorsS.deletePredictor(predictor).subscribe((response) => { - this.getAllMyPredictors(); - }, (error) =>{ - if (error.error == "Predictor with name = {name} deleted") { - alert("Greška pri brisanju modela!"); - } - }); - } - - + deleteThisPredictor(predictor: Predictor): void{ + shared.openYesNoDialog('Brisanje prediktora','Da li ste sigurni da želite da obrišete prediktor?',() => { + this.predictorsS.deletePredictor(predictor).subscribe((response) => { + this.getAllMyPredictors(); + }, (error) =>{ + if (error.error == "Predictor with name = {name} deleted") { + shared.openDialog("Obaveštenje", "Greška prilikom brisanja prediktora."); + } + }); + }); } getAllMyPredictors(): void{ - this.predictorsS.getMyPredictors().subscribe(m => { - this.predictors = m; + this.predictorsS.getMyPredictors().subscribe(p => { + this.predictors = p; }); } diff --git a/frontend/src/app/_services/datasets.service.ts b/frontend/src/app/_services/datasets.service.ts index c3281be6..b2272f0a 100644 --- a/frontend/src/app/_services/datasets.service.ts +++ b/frontend/src/app/_services/datasets.service.ts @@ -29,10 +29,10 @@ export class DatasetsService { } editDataset(dataset: Dataset): Observable<Dataset> { - return this.http.put<Dataset>(`${Configuration.settings.apiURL}/dataset/`, dataset, { headers: this.authService.authHeader() }); + return this.http.put<Dataset>(`${Configuration.settings.apiURL}/dataset/` + dataset._id, dataset, { headers: this.authService.authHeader() }); } deleteDataset(dataset: Dataset) { - return this.http.delete(`${Configuration.settings.apiURL}/dataset/` + dataset.name, { headers: this.authService.authHeader(), responseType: "text" }); + return this.http.delete(`${Configuration.settings.apiURL}/dataset/` + dataset._id, { headers: this.authService.authHeader(), responseType: "text" }); } } diff --git a/frontend/src/app/_services/predictors.service.ts b/frontend/src/app/_services/predictors.service.ts index 9e8383aa..a24ee708 100644 --- a/frontend/src/app/_services/predictors.service.ts +++ b/frontend/src/app/_services/predictors.service.ts @@ -24,7 +24,7 @@ export class PredictorsService { } deletePredictor(predictor: Predictor) { - return this.http.delete(`${Configuration.settings.apiURL}/predictor/` + predictor.name, { headers: this.authService.authHeader(), responseType: "text" }); + return this.http.delete(`${Configuration.settings.apiURL}/predictor/` + predictor._id, { headers: this.authService.authHeader(), responseType: "text" }); } getMyPredictors(): Observable<Predictor[]> { diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index e22f7a88..238668d9 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -20,6 +20,7 @@ const routes: Routes = [ /*{ path: 'add-model', component: AddModelComponent, data: { title: 'Dodaj model' } },*/ { path: 'experiment', component: ExperimentComponent, data: { title: 'Dodaj eksperiment' } }, { path: 'training', component: TrainingComponent, data: { title: 'Treniraj model' } }, + { path: 'training/:id', component: TrainingComponent, data: { title: 'Treniraj model' } }, { path: 'my-datasets', component: MyDatasetsComponent, canActivate: [AuthGuardService], data: { title: 'Moji izvori podataka' } }, { path: 'my-models', component: MyModelsComponent, canActivate: [AuthGuardService], data: { title: 'Moji modeli' } }, { path: 'my-predictors', component: MyPredictorsComponent, canActivate: [AuthGuardService], data: { title: 'Moji trenirani modeli' } }, @@ -28,6 +29,7 @@ const routes: Routes = [ { path: 'browse-datasets', component: FilterDatasetsComponent, data: { title: 'Javni izvori podataka' } }, { path: 'browse-predictors', component: BrowsePredictorsComponent, data: { title: 'Javni trenirani modeli' } }, { path: 'predict/:id', component: PredictComponent, data: { title: 'Predvidi vrednosti' } }, + ]; @NgModule({ diff --git a/frontend/src/app/experiment/experiment.component.html b/frontend/src/app/experiment/experiment.component.html index e46f5bd9..62236cce 100644 --- a/frontend/src/app/experiment/experiment.component.html +++ b/frontend/src/app/experiment/experiment.component.html @@ -13,150 +13,132 @@ </div> <div id="carouselExampleControls" class="carousel slide px-5 mt-5" data-bs-wrap="false" data-bs-ride="carousel" data-bs-interval="false"> - <div class="carousel-inner"> - <div class="carousel-item active mt-2"> - <h2 class="mb-5">1. Izvor podataka</h2> - <app-dataset-load (selectedDatasetChangeEvent)="updateDataset($event)"></app-dataset-load> - </div> + <div class="carousel-inner"> + <div class="carousel-item active mt-2"> + <h2 class="mb-5">1. Izvor podataka</h2> + <app-dataset-load (selectedDatasetChangeEvent)="updateDataset($event)"></app-dataset-load> + </div> - <div class="carousel-item mt-2"> - <h2 class="mb-4">2. Preprocesiranje</h2> + <div class="carousel-item mt-2"> + <h2 class="mb-4">2. Preprocesiranje</h2> - <div class="px-5"> - <h3>Biranje ulaznih i izlaznih kolona:</h3> - <div *ngIf="selectedDataset"> - <div class="row"> - <div class="col d-flex justify-content-center"> - <h3>Izaberite ulazne kolone:</h3> - <div id="divInputs" class="form-check mt-2"> - <br> - <div *ngFor="let item of selectedDataset.columnInfo; let i = index"> - <input class="form-check-input" type="checkbox" value="{{item.columnName}}" - id="cb_{{item.columnName}}" name="cbsNew" - [checked]="experiment.outputColumn != item.columnName" - [disabled]="experiment.outputColumn == item.columnName" - (click)="checkedColumnsChanged(item, 0)"> - <label class="form-check-label" for="cb_{{item.columnName}}"> + <div class="px-5"> + <h3>Biranje ulaznih i izlaznih kolona:</h3> + <div *ngIf="selectedDataset"> + <div class="row"> + <div class="col d-flex justify-content-center"> + <h3>Izaberite ulazne kolone:</h3> + <div id="divInputs" class="form-check mt-2"> + <br> + <div *ngFor="let item of selectedDataset.columnInfo; let i = index"> + <input class="form-check-input" type="checkbox" value="{{item.columnName}}" id="cb_{{item.columnName}}" name="cbsNew" [checked]="experiment.outputColumn != item.columnName" [disabled]="experiment.outputColumn == item.columnName" (change)="checkedColumnsChanged(item, 0); resetColumnEncodings();"> + <label class="form-check-label" for="cb_{{item.columnName}}"> {{item.columnName}} </label> + </div> </div> </div> - </div> - <div class="col d-flex justify-content-left"> - <h3>Izaberite izlaznu kolonu:</h3> - <div id="divOutputs" class="form-check mt-2"> - <br> - <div *ngFor="let item of selectedDataset.columnInfo; let i = index"> - <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);"> - <label class="form-check-label" for="rb_{{item.columnName}}"> + <div class="col d-flex justify-content-left"> + <h3>Izaberite izlaznu kolonu:</h3> + <div id="divOutputs" class="form-check mt-2"> + <br> + <div *ngFor="let item of selectedDataset.columnInfo; let i = index"> + <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; checkedColumnsChanged(item, 1); resetColumnEncodings();" + checked> + <label class="form-check-label" for="rb_{{item.columnName}}"> {{item.columnName}} </label> + </div> </div> </div> </div> </div> - </div> - - <h3 class="mt-5">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"> - <label for="delRows" class="form-check-label">Obriši sve + + + <div class="mt-5 mb-3 mx-3" *ngIf="countSelectedNullCols() == 0"> + <h3 class="border p-2 text-center"><i>Izabrane kolone nemaju nedostajuće vrednosti koje možete popuniti.</i></h3> + </div> + + <div *ngIf="countSelectedNullCols() != 0"> + <h3 class="mt-5">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"> + <label for="delRows" class="form-check-label ">Obriši sve redove sa nedostajućim vrednostima ({{selectedDataset.nullRows}} od {{selectedDataset.rowCount}})</label><br> - <input type="radio" [(ngModel)]="experiment.nullValues" [value]="NullValueOptions.DeleteColumns" - class="form-check-input" value="deleteCols" name="fillMissing" id="delCols" data-bs-toggle="collapse" - data-bs-target="#fillMissingCustom.show"> - <label for="delCols" class="form-check-label">Obriši sve + <input type="radio" [(ngModel)]="experiment.nullValues " [value]="NullValueOptions.DeleteColumns " class="form-check-input" value="deleteCols" name="fillMissing " id="delCols" data-bs-toggle="collapse" data-bs-target="#fillMissingCustom.show"> + <label for="delCols" class="form-check-label ">Obriši sve kolone sa nedostajućim vrednostima ({{countSelectedNullCols()}} od {{selectedDataset.columnInfo.length}})</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)"> - <label for="replace" class="form-check-label">Izabraću + <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="getSelectedColumnsArrayWithoutNullVals().length > 0" > - <label class="text-center form-control mx-3 text-secondary"> + <div class="collapse" id="fillMissingCustom"> + <div> + <label for="columnReplacers" class="form-label">Unesite zamenu za svaku kolonu:</label> + <div class="my-3 " *ngIf="getSelectedColumnsArrayWithoutNullVals().length> 0"> + <label class="text-center form-control mx-3 text-secondary"> Kolone <span style="font-style: italic;" *ngFor="let colname of getSelectedColumnsArrayWithoutNullVals(); let i = index"> <span *ngIf="i != getSelectedColumnsArrayWithoutNullVals().length - 1">{{colname}}, </span> <span *ngIf="i == getSelectedColumnsArrayWithoutNullVals().length - 1">{{colname}} </span> </span> nemaju nedostajućih vrednosti za popunjavanje. </label> - </div> - <div id="columnReplacers"> - <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}} <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"> - 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"> - <div class="input-group-prepend"> - <label [for]="'fillCol_'+column.columnName" class="form-control"> + </div> + <div id="columnReplacers"> + <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}} + <span class="small" style="color:gray;">({{column.numNulls}} null)</span> + </span> + + <div class="d-flex flex-row justify-content-end"> + <div class="flex-grow-3 mx-3 me-auto"> + <div class="input-group"> + <div class="input-group-prepend"> + <label [for]="'fillCol_'+column.columnName" class="form-control"> Zameni <input type="radio" [id]="'fillCol_'+column.columnName" [name]="'delOp_'+column.columnName"> </label> - </div> - <input type="text" class="form-control" [id]="'fillText_'+column.columnName" - (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); checkFillColRadio(column.columnName);"> + </div> + <input type="text" class="form-control" [id]="'fillText_'+column.columnName" (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); 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" - *ngIf="!column.isNumber && column.numNulls > 0" - (change)="replace($event, column); checkFillColRadio(column.columnName);"> + <select [id]="'replaceOptions'+i" class="form-control btn-outline-primary" *ngIf="!column.isNumber && column.numNulls > 0" (change)="replace($event, column); checkFillColRadio(column.columnName);"> <option *ngFor="let option of column.uniqueValues" [value]="option"> {{ option }} </option> </select> + </div> + </div> </div> - </div> - </div> - - <div class="flex-shrink-1 mx-3"> - <div class="input-group"> - <label class="form-control" [for]="'delCol_'+column.columnName">Izbriši + + <div class="flex-shrink-1 mx-3"> + <div class="input-group"> + <label class="form-control" [for]="'delCol_'+column.columnName">Izbriši kolonu <input type="radio" [id]="'delCol_'+column.columnName" [name]="'delOp_'+column.columnName" (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 + </div> + </div> + + <div class="flex-shrink-1 mx-3"> + <div class="input-group"> + <label class="form-control" [for]="'delRows_'+column.columnName">Izbriši redove <input type="radio" [id]="'delRows_'+column.columnName" [name]="'delOp_'+column.columnName" checked (change)="emptyFillTextInput(column.columnName)"></label> + </div> + </div> </div> </div> </div> @@ -165,96 +147,109 @@ </div> </div> </div> - </div> - - <div id="randomOptions" class="mt-5"> - <div class="p-2 m-2"> - <label for="type" class="form-check-label">Želite li da redosled podataka bude nasumičan?</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"> + + <div id="randomOptions" class="mt-5"> + <div class="p-2 m-2"> + <label for="type" class="form-check-label">Želite li da redosled podataka bude nasumičan?</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: <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="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 m-2"> - <label for="percentage" class="form-label">Procenat podataka koji se uzima za trening + + <div class="row p-2 m-2"> + <label for="percentage" class="form-label">Procenat podataka koji se uzima za trening skup:</label> - <input id="percentage" type="number" class="form-control mx-3" style=" max-width: 15%" min="10" max="90" step="10" value="90" - [(ngModel)]="tempTestSetDistribution" [disabled]="!experiment.randomTestSet"> + <input id="percentage" type="number" class="form-control mx-3" style=" max-width: 15%" min="10" max="90" step="10" value="90" [(ngModel)]="tempTestSetDistribution" [disabled]="!experiment.randomTestSet"> + </div> </div> </div> - </div> - - <div id="encodingForColumns" class="row px-3 my-5"> - <div class="col-1"> - <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 id="encodingsForColumns" class="px-3 my-5"> + <label for="encoding" class="col-form-label mb-2">Enkoding za izabrane kolone:</label> + + <div class="row d-flex flex-row justify-content-between align-items-center"> + <div class="col-5" *ngFor="let item of [].constructor(selectedColumnsInfoArray.length); let i = index"> + <div class="input-group mb-2"> + <div class="input-group-prepend"> + <span class="input-group-text">{{selectedColumnsInfoArray[i].columnName}}</span> + </div> + <select [id]="'encodingOption_'+i" class="form-select" [(ngModel)]="experiment.encodings[i].encoding"> + <option + *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" + [value]="option"> + {{ optionName }} + </option> + </select> + </div> + </div> + </div> </div> + </div> - - </div> - </div> + </div> - <div class="carousel-item mt-2"> - <h2 class="mb-4">3. Dodaj eskperiment</h2> + <div class="carousel-item mt-2"> + <h2 class="mb-4">3. Dodaj eskperiment</h2> - <div class="row"> - <div class="col"></div> - <div class="col-8"> - <label for="name" class="col-form-label">Naziv eksperimenta:</label> - <input type="text" class="form-control mb-3" 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> - <div class="form-group row mt-5 mb-3"> - <div class="col"></div> - <button class="btn btn-lg col-4" style="background-color:#003459; color:white;" (click)="saveExperiment();">Sačuvaj + <div class="row"> + <div class="col"></div> + <div class="col-8"> + <label for="name" class="col-form-label">Naziv eksperimenta:</label> + <input type="text" class="form-control mb-3" 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> + <label for="desc" class="col-sm-2 col-form-label mt-3">Tip problema:</label> + <div class="col-4"> + <select id="typeOptions" class="form-select" name="type" [(ngModel)]="experiment.type"> + <option + *ngFor="let option of Object.keys(ProblemType); let optionName of Object.values(ProblemType)" + [value]="option"> + {{ optionName }} + </option> + </select> + </div> + <div class="form-group row mt-5 mb-3"> + <div class="col"></div> + <button class="btn btn-lg col-4" style="background-color:#003459; color:white;" (click)="saveExperiment();">Sačuvaj eksperiment</button> - <div class="col"></div> + <div class="col"></div> + </div> </div> + <div class="col"></div> </div> - <div class="col"></div> </div> + </div> - </div> - <div class="m-3 d-flex flex-row justify-content-between align-items-center" style=" margin-left: auto;"> - <button mat-fab color="primary" data-bs-target="#carouselExampleControls" data-bs-slide="prev"> - <mat-icon>arrow_backward</mat-icon> - </button> - <button mat-fab color="primary" data-bs-target="#carouselExampleControls" data-bs-slide="next"> - <mat-icon>arrow_forward</mat-icon> - </button> - </div> + <div class="m-3 d-flex flex-row justify-content-between align-items-center" style=" margin-left: auto;"> + <button mat-fab color="primary" data-bs-target="#carouselExampleControls" data-bs-slide="prev"> + <mat-icon>arrow_backward</mat-icon> + </button> + <button mat-fab color="primary" data-bs-target="#carouselExampleControls" data-bs-slide="next"> + <mat-icon>arrow_forward</mat-icon> + </button> + </div> </div> </div> </div>
\ No newline at end of file diff --git a/frontend/src/app/experiment/experiment.component.ts b/frontend/src/app/experiment/experiment.component.ts index b5e1d1f4..2d0f6ec5 100644 --- a/frontend/src/app/experiment/experiment.component.ts +++ b/frontend/src/app/experiment/experiment.component.ts @@ -1,10 +1,11 @@ import { Component, OnInit } from '@angular/core'; import Experiment, { NullValReplacer, NullValueOptions, ReplaceWith, Encoding } from '../_data/Experiment'; -import Model from '../_data/Model'; +import Model,{ProblemType} from '../_data/Model'; import Dataset, { ColumnInfo } from '../_data/Dataset'; import { ModelsService } from '../_services/models.service'; import Shared from '../Shared'; import { ExperimentsService } from '../_services/experiments.service'; +import { ColumnEncoding } from '../_data/Experiment'; @Component({ selector: 'app-experiment', @@ -21,8 +22,9 @@ export class ExperimentComponent implements OnInit { NullValueOptions = NullValueOptions; ReplaceWith = ReplaceWith; Encoding = Encoding; + ColumnEncoding = ColumnEncoding; Object = Object; - + ProblemType=ProblemType; selectedColumnsInfoArray: ColumnInfo[] = []; selectedNotNullColumnsArray: string[] = []; @@ -38,6 +40,17 @@ export class ExperimentComponent implements OnInit { this.selectedDataset = dataset; this.selectedColumnsInfoArray = this.selectedDataset.columnInfo; this.selectedNotNullColumnsArray = []; + this.experiment.outputColumn = this.selectedDataset.columnInfo[this.selectedDataset.columnInfo.length - 1].columnName; + + this.resetColumnEncodings(); + console.log(this.experiment.encodings); + } + + resetColumnEncodings() { + this.experiment.encodings = []; + for (let i = 0; i < this.selectedColumnsInfoArray.length; i++) { + this.experiment.encodings.push(new ColumnEncoding(this.selectedColumnsInfoArray[i].columnName, Encoding.Label)); + } } getInputById(id: string): HTMLInputElement { @@ -179,13 +192,14 @@ export class ExperimentComponent implements OnInit { this.experiment.randomTestSetDistribution = 1 - Math.round(this.tempTestSetDistribution / 100 * 10) / 10; - //console.log("Eksperiment:", this.experiment); + console.log("Eksperiment:", this.experiment); this.experimentsService.addExperiment(this.experiment).subscribe((response) => { this.experiment = response; - this.selectedColumnsInfoArray = []; + this.selectedColumnsInfoArray = []; this.selectedNotNullColumnsArray = []; + this.experiment.encodings = []; Shared.openDialog("Obaveštenje", "Eksperiment je uspešno kreiran."); }, (error) => { diff --git a/frontend/src/app/training/training.component.html b/frontend/src/app/training/training.component.html index 0ce4cc89..672e75fb 100644 --- a/frontend/src/app/training/training.component.html +++ b/frontend/src/app/training/training.component.html @@ -23,7 +23,7 @@ </div> <h2 class="mt-5 mb-2">2. Izaberite model</h2> - <app-model-load (selectedModelChangeEvent)="selectModel($event)"></app-model-load> + <app-model-load (selectedModelChangeEvent)="selectModel($event)" [forExperiment]="selectedExperiment"></app-model-load> <h2 class="my-5">3. Treniranje modela</h2> |