diff options
31 files changed, 323 insertions, 233 deletions
diff --git a/backend/api/api/Controllers/DatasetController.cs b/backend/api/api/Controllers/DatasetController.cs index e4741412..849d9884 100644 --- a/backend/api/api/Controllers/DatasetController.cs +++ b/backend/api/api/Controllers/DatasetController.cs @@ -144,7 +144,6 @@ namespace api.Controllers [Authorize(Roles = "User,Guest")] public async Task<ActionResult<Dataset>> Post([FromBody] Dataset dataset) { - Console.WriteLine("PROBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); string uploaderId = getUserId(); dataset.uploaderId = uploaderId; @@ -196,7 +195,7 @@ namespace api.Controllers string ext = ".csv"; - //nesto + //Check Directory if (!Directory.Exists(folderPath)) @@ -279,19 +278,4 @@ namespace api.Controllers } } -} - -/* -{ - "_id": "", - "name": "name", - "description": "description", - "header" : ["ag","rt"], - "fileId" : "652", - "extension": "csb", - "isPublic" : true, - "accessibleByLink": true, - "dateCreated": "dateCreated", - "lastUpdated" : "proba12" -} -*/
\ No newline at end of file +}
\ No newline at end of file diff --git a/backend/api/api/Controllers/ModelController.cs b/backend/api/api/Controllers/ModelController.cs index 39eb7830..be30ae6f 100644 --- a/backend/api/api/Controllers/ModelController.cs +++ b/backend/api/api/Controllers/ModelController.cs @@ -211,6 +211,8 @@ namespace api.Controllers return BadRequest("Bad parameters!");*/ model.uploaderId = getUserId(); + model.dateCreated = DateTime.Now; + model.lastUpdated = DateTime.Now; var existingModel = _modelService.GetOneModel(model.uploaderId, model.name); @@ -232,6 +234,44 @@ namespace api.Controllers } } + // POST api/<ModelController>/stealModel + [HttpPost("stealModel")] + [Authorize(Roles = "User,Guest")] + public ActionResult<Model> StealModel([FromBody] Model model)//, bool overwrite) + { + bool overwrite = false; + //username="" ako je GUEST + //Experiment e = _experimentService.Get(model.experimentId); umesto 1 ide e.inputColumns.Length TODO!!!!!!!!!!!!!!!!! + //model.inputNeurons = e.inputColumns.Length; + /*if (_modelService.CheckHyperparameters(1, model.hiddenLayerNeurons, model.hiddenLayers, model.outputNeurons) == false) + return BadRequest("Bad parameters!");*/ + + model.uploaderId = getUserId(); + model._id = ""; + model.dateCreated = DateTime.Now; + model.lastUpdated = DateTime.Now; + model.isPublic = false; + + var existingModel = _modelService.GetOneModel(model.uploaderId, model.name); + + + if (existingModel != null && !overwrite && model.validationSize < 1 && model.validationSize > 0) + return NotFound($"Model already exisits or validation size is not between 0-1"); + else + { + //_modelService.Create(model); + //return Ok(); + if (existingModel == null) + _modelService.Create(model); + else + { + _modelService.Replace(model); + } + + return CreatedAtAction(nameof(Get), new { id = model._id }, model); + } + } + // PUT api/<ModelController>/{name} [HttpPut("{name}")] [Authorize(Roles = "User,Guest")] diff --git a/backend/api/api/Models/Model.cs b/backend/api/api/Models/Model.cs index a807316f..bbbf201e 100644 --- a/backend/api/api/Models/Model.cs +++ b/backend/api/api/Models/Model.cs @@ -14,18 +14,14 @@ namespace api.Models public string name { get; set; } public string description { get; set; } - //datetime public DateTime dateCreated { get; set; } public DateTime lastUpdated { get; set; } - //proveriti id - //public string experimentId { get; set; } //Neural net training public string type { get; set; } public string optimizer { get; set; } public string lossFunction { get; set; } - //public int inputNeurons { get; set; } public int hiddenLayers { get; set; } public string batchSize { get; set; } public string learningRate { get; set; } @@ -36,8 +32,6 @@ namespace api.Models public string[] metrics { get; set; } public int epochs { get; set; } - //public bool isTrained { get; set; } - //public NullValues[] nullValues { get; set; } public bool randomOrder { get; set; } public bool randomTestSet { get; set; } public float randomTestSetDistribution { get; set; } diff --git a/backend/api/api/Models/Predictor.cs b/backend/api/api/Models/Predictor.cs index 530257b2..5a7b5eda 100644 --- a/backend/api/api/Models/Predictor.cs +++ b/backend/api/api/Models/Predictor.cs @@ -18,38 +18,25 @@ namespace api.Models public string experimentId { get; set; } public string modelId { get; set; } public string h5FileId { get; set; } - public Metric[] metrics { get; set; } - public Metric[] finalMetrics { get; set; } - } - public class Metric + //public Metric[] metrics { get; set; } + + public float[] metricsLoss { get; set; } + public float[] metricsValLoss { get; set; } + public float[] metricsAcc { get; set; } + public float[] metricsValAcc { get; set; } + public float[] metricsMae { get; set; } + public float[] metricsValMae { get; set; } + public float[] metricsMse { get; set; } + public float[] metricsValMse { get; set; } + //public Metric[] finalMetrics { get; set; } + } + + /*public class Metric { string Name { get; set; } string JsonValue { get; set; } - } - -} - -/** -* Paste one or more documents here - -{ - "_id": { - "$oid": "625dc348b7856ace8a6f8702" - - }, - "uploaderId" : "6242ea59486c664208d4255c", - "inputs": ["proba", - "proba2", - "proba3" - ], - "output" : "izlaz", - "isPublic" : true, - "accessibleByLink" : true, - "dateCreated" : "2022-04-11T20:33:26.937+00:00", - "experimentId" : "Neki id eksperimenta", - "modelId" : "Neki id eksperimenta", - "h5FileId" : "Neki id eksperimenta", - "metrics" : [{ }] -}*/
\ No newline at end of file + }*/ + +}
\ No newline at end of file diff --git a/backend/api/api/Program.cs b/backend/api/api/Program.cs index cf64d58d..5977e843 100644 --- a/backend/api/api/Program.cs +++ b/backend/api/api/Program.cs @@ -37,7 +37,7 @@ builder.Services.AddScoped<IFileService, FileService>(); builder.Services.AddScoped<IJwtToken, JwtToken>(); builder.Services.AddScoped<IExperimentService, ExperimentService>(); builder.Services.AddHostedService<TempFileService>(); -builder.Services.AddHostedService<FillAnEmptyDb>(); +//builder.Services.AddHostedService<FillAnEmptyDb>(); //Ml Api Ip Filter builder.Services.AddScoped<MlApiCheckActionFilter>(container => diff --git a/backend/api/api/Services/DatasetService.cs b/backend/api/api/Services/DatasetService.cs index f38a363b..0b84721e 100644 --- a/backend/api/api/Services/DatasetService.cs +++ b/backend/api/api/Services/DatasetService.cs @@ -104,16 +104,6 @@ namespace api.Services return dataset._id; } - /* -public bool CheckDb() -{ - Dataset? dataset = null; - dataset = _dataset.Find(dataset => dataset.username == "igrannonica").FirstOrDefault(); - - if (dataset != null) - return false; - else - return true; -}*/ + } } diff --git a/backend/api/api/Services/FillAnEmptyDb.cs b/backend/api/api/Services/FillAnEmptyDb.cs index 811e723a..cd35dc78 100644 --- a/backend/api/api/Services/FillAnEmptyDb.cs +++ b/backend/api/api/Services/FillAnEmptyDb.cs @@ -54,7 +54,7 @@ namespace api.Services dataset._id = ""; dataset.uploaderId = "000000000000000000000000"; - dataset.name = "Titanik dataset(public)"; + dataset.name = "Titanik dataset (public)"; dataset.description = "Titanik dataset"; dataset.fileId = _fileService.GetFileId(fullPath); dataset.extension = ".csv"; @@ -277,6 +277,7 @@ namespace api.Services model.lossFunction = "sparse_categorical_crossentropy"; model.hiddenLayers = 5; model.batchSize = "64"; + model.learningRate = "1"; model.outputNeurons = 0; model.layers = new[] { @@ -368,7 +369,7 @@ namespace api.Services dataset._id = ""; dataset.uploaderId = "000000000000000000000000"; dataset.name = "IMDB-Movie-Data Dataset (public)"; - dataset.description = "IMDB-Movie-Data Dataset(public)"; + dataset.description = "IMDB-Movie-Data Dataset (public)"; dataset.fileId = _fileService.GetFileId(fullPath); dataset.extension = ".csv"; dataset.isPublic = true; @@ -421,8 +422,8 @@ namespace api.Services model._id = ""; model.uploaderId = "000000000000000000000000"; - model.name = "IMDB model"; - model.description = "IMDB model"; + model.name = "IMDB model (public)"; + model.description = "IMDB model (public)"; model.dateCreated = DateTime.Now; model.lastUpdated = DateTime.Now; model.type = "regresioni"; @@ -579,8 +580,8 @@ namespace api.Services model._id = ""; model.uploaderId = "000000000000000000000000"; - model.name = "Churn model"; - model.description = "Churn model"; + model.name = "Churn model (public)"; + model.description = "Churn model (public)"; model.dateCreated = DateTime.Now; model.lastUpdated = DateTime.Now; model.type = "binarni-klasifikacioni"; diff --git a/backend/api/api/Services/MlConnectionService.cs b/backend/api/api/Services/MlConnectionService.cs index 0ecdb1af..6a307e0d 100644 --- a/backend/api/api/Services/MlConnectionService.cs +++ b/backend/api/api/Services/MlConnectionService.cs @@ -63,19 +63,6 @@ namespace api.Services foreach (var connection in ChatHub.getAllConnectionsOfUser(id)) await _ichat.Clients.Client(connection).SendAsync("NotifyDataset",newDataset.name,newDataset._id); - - string proba = ""; - - for (int i = 0; i < newDataset.cMatrix.Length; i++) - { - proba = i +" "; - for (int j = 0; j < newDataset.cMatrix[i].Length; j++) - proba += newDataset.cMatrix[i][j] + "f, "; - - Console.WriteLine(proba); - proba = ""; - } - return; } diff --git a/backend/api/api/appsettings.json b/backend/api/api/appsettings.json index 44d63ac3..b502efeb 100644 --- a/backend/api/api/appsettings.json +++ b/backend/api/api/appsettings.json @@ -16,22 +16,26 @@ "UserStoreDatabaseSettings": { /* LocalHost*/ - /*"ConnectionString": "mongodb://127.0.0.1:27017/", + "ConnectionString": "mongodb://127.0.0.1:27017/", "DatabaseName": "si_project", "CollectionName": "users", "DatasetCollectionName": "Dataset", "ModelCollectionName": "Model", "PredictorCollectionName": "Predictor", "FilesCollectionName": "Files", - "ExperimentCollectionName": "Experiment"*/ + "ExperimentCollectionName": "Experiment" + /* "ConnectionString": "mongodb+srv://si_user:si_user@sidatabase.twtfm.mongodb.net/myFirstDatabase?retryWrites=true&w=majority", + + "ConnectionString": "mongodb+srv://si_user:si_user@sidatabase.twtfm.mongodb.net/myFirstDatabase?retryWrites=true&w=majority", + 529394dd526811e059dfb5f8f76597ffd90b2fea "DatabaseName": "si_db", "CollectionName": "users", "DatasetCollectionName": "Dataset", "ModelCollectionName": "Model", "PredictorCollectionName": "Predictor", "FilesCollectionName": "Files", - "ExperimentCollectionName": "Experiment" + "ExperimentCollectionName": "Experiment" */ } }
\ No newline at end of file diff --git a/backend/microservice/api/controller.py b/backend/microservice/api/controller.py index 7852b63d..c82634a2 100644 --- a/backend/microservice/api/controller.py +++ b/backend/microservice/api/controller.py @@ -69,22 +69,30 @@ def train(): #dataset, paramsModel, paramsExperiment, callback) - filepath,result,finalMetrics= newmlservice.train(data, paramsModel, paramsExperiment,paramsDataset, train_callback) + filepath,histMetrics= newmlservice.train(data, paramsModel, paramsExperiment,paramsDataset, train_callback) """ f = request.json['filepath'] dataset = pd.read_csv(f) filepath,result=newmlservice.train(dataset,request.json['model'],train_callback) print(result) """ - - + #m = [] + #for attribute, value in result.items(): + #m.append(histMetrics(attribute,str(value)).__dict__) + ''' + m = [] + for attribute, value in result.items(): + m.append({"Name" : attribute, "JsonValue" : value})) + + print("**************************************************************") + print(m) + + print("**************************************************************") + ''' url = config.api_url + "/file/h5" files = {'file': open(filepath, 'rb')} r=requests.post(url, files=files,data={"uploaderId":paramsExperiment['uploaderId']}) fileId=r.text - m = [] - for attribute, value in result.items(): - m.append({"Name" : attribute, "JsonValue" : value}) predictor = { "_id" : "", "uploaderId" : paramsModel["uploaderId"], @@ -95,14 +103,21 @@ def train(): "experimentId" : paramsExperiment["_id"], "modelId" : paramsModel["_id"], "h5FileId" : fileId, - "metrics" : m, - "finalMetrics":finalMetrics - + "metricsLoss":histMetrics[0], + "metricsValLoss":histMetrics[1], + "metricsAcc":histMetrics[2], + "metricsValAcc":histMetrics[3], + "metricsMae":histMetrics[4], + "metricsValMae":histMetrics[5], + "metricsMse":histMetrics[6], + "metricsValMse":histMetrics[7] } #print(predictor) + url = config.api_url + "/Predictor/add" r = requests.post(url, json=predictor).text - print(r) + + #print(r) return r @app.route('/predict', methods = ['POST']) diff --git a/backend/microservice/api/newmlservice.py b/backend/microservice/api/newmlservice.py index fd21f8ce..85be0c2f 100644 --- a/backend/microservice/api/newmlservice.py +++ b/backend/microservice/api/newmlservice.py @@ -303,7 +303,7 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): ###OPTIMIZATORI print(paramsModel['optimizer']) if(paramsModel['optimizer']=='Adam'): - opt=tf.keras.optimizers.Adam(learning_rate=3) + opt=tf.keras.optimizers.Adam(learning_rate=float(paramsModel['learningRate'])) elif(paramsModel['optimizer']=='Adadelta'): opt=tf.keras.optimizers.Adadelta(learning_rate=float(paramsModel['learningRate'])) @@ -370,7 +370,7 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): - classifier.compile(loss =paramsModel["lossFunction"] , optimizer =opt, metrics = ['mae','mse']) + classifier.compile(loss =paramsModel["lossFunction"] , optimizer =opt, metrics = ['accuracy','mae','mse']) history=classifier.fit( x=x_train, y=y_train, epochs = paramsModel['epochs'],batch_size=int(paramsModel['batchSize']),callbacks=callback(x_test, y_test,paramsModel['_id']),validation_data=(x_val, y_val)) @@ -383,9 +383,9 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): scores = classifier.evaluate(x_test, y_test) #print("\n%s: %.2f%%" % (classifier.metrics_names[1], scores[1]*100)) - + ''' classifier.save(filepath, save_format='h5') - metrics={} + macro_averaged_precision=sm.precision_score(y_test, y_pred, average = 'macro') micro_averaged_precision=sm.precision_score(y_test, y_pred, average = 'micro') macro_averaged_recall=sm.recall_score(y_test, y_pred, average = 'macro') @@ -393,20 +393,20 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): macro_averaged_f1=sm.f1_score(y_test, y_pred, average = 'macro') micro_averaged_f1=sm.f1_score(y_test, y_pred, average = 'micro') - metrics= { - "macro_averaged_precision" :float(macro_averaged_precision), - "micro_averaged_precision" : float(micro_averaged_precision), - "macro_averaged_recall" : float(macro_averaged_recall), - "micro_averaged_recall" : float(micro_averaged_recall), - "macro_averaged_f1" : float(macro_averaged_f1), - "micro_averaged_f1" : float(micro_averaged_f1) - } - + metrics= [ + {"Name":"macro_averaged_precision", "JsonValue":str(macro_averaged_precision)}, + {"Name":"micro_averaged_precision" ,"JsonValue":str(micro_averaged_precision)}, + {"Name":"macro_averaged_recall", "JsonValue":str(macro_averaged_recall)}, + {"Name":"micro_averaged_recall" ,"JsonValue":str(micro_averaged_recall)}, + {"Name":"macro_averaged_f1","JsonValue": str(macro_averaged_f1)}, + {"Name":"micro_averaged_f1", "JsonValue": str(micro_averaged_f1)} + ] + ''' #vizuelizacija u python-u #from ann_visualizer.visualize import ann_viz; #ann_viz(classifier, title="My neural network") - return filepath,hist,metrics + return filepath,[hist['loss'],hist['val_loss'],hist['accuracy'],hist['val_accuracy'],hist['mae'],hist['val_mae'],hist['mse'],hist['val_mse']] elif(problem_type=='binarni-klasifikacioni'): #print('*************************************************************************binarni') @@ -444,6 +444,7 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): history=classifier.fit( x=x_train, y=y_train, epochs = paramsModel['epochs'],batch_size=int(paramsModel['batchSize']),callbacks=callback(x_test, y_test,paramsModel['_id']),validation_data=(x_val, y_val)) hist=history.history + y_pred=classifier.predict(x_test) y_pred=(y_pred>=0.5).astype('int') @@ -452,7 +453,7 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): # ann_viz(classifier, title="My neural network") classifier.save(filepath, save_format='h5') - + """ accuracy = float(sm.accuracy_score(y_test,y_pred)) precision = float(sm.precision_score(y_test,y_pred)) recall = float(sm.recall_score(y_test,y_pred)) @@ -461,22 +462,9 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): f1 = float(sm.f1_score(y_test,y_pred)) fpr, tpr, _ = sm.roc_curve(y_test,y_pred) logloss = float(sm.log_loss(y_test, y_pred)) - metrics= { - "accuracy" : accuracy, - "precision" : precision, - "recall" : recall, - "specificity" : specificity, - "f1" : f1, - "tn" : float(tn), - "fp" : float(fp), - "fn" : float(fn), - "tp" : float(tp), - "fpr" : fpr.tolist(), - "tpr" : tpr.tolist(), - "logloss" : logloss - } + """ - return filepath,hist,metrics + return filepath,[hist['loss'],hist['val_loss'],hist['accuracy'],hist['val_accuracy'],hist['mae'],hist['val_mae'],hist['mse'],hist['val_mse']] elif(problem_type=='regresioni'): reg=paramsModel['layers'][0]['regularisation'] @@ -514,13 +502,15 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): history=classifier.fit( x=x_train, y=y_train, epochs = paramsModel['epochs'],batch_size=int(paramsModel['batchSize']),callbacks=callback(x_test, y_test,paramsModel['_id']),validation_data=(x_val, y_val)) hist=history.history + y_pred=classifier.predict(x_test) #print(classifier.evaluate(x_test, y_test)) classifier.save(filepath, save_format='h5') - + ''' mse = float(sm.mean_squared_error(y_test,y_pred)) + mae = float(sm.mean_absolute_error(y_test,y_pred)) mape = float(sm.mean_absolute_percentage_error(y_test,y_pred)) rmse = float(np.sqrt(sm.mean_squared_error(y_test,y_pred))) @@ -531,16 +521,19 @@ def train(dataset, paramsModel,paramsExperiment,paramsDataset,callback): n = 40 k = 2 adj_r2 = float(1 - ((1-r2)*(n-1)/(n-k-1))) - metrics= {"mse" : mse, - "mae" : mae, - "mape" : mape, - "rmse" : rmse, - "rmsle" : rmsle, - "r2" : r2, - "adj_r2" : adj_r2 - } - - return filepath,hist,metrics + + metrics= [ + {"Name":"mse","JsonValue":str(mse)}, + + {"Name":"mae","JsonValue":str(mae)}, + {"Name":"mape","JsonValue":str( mape)}, + {"Name":"rmse","JsonValue":str(rmse)}, + {"Name":"rmsle","JsonValue":str(rmsle)}, + {"Name":"r2","JsonValue":str( r2)}, + {"Name":"adj_r2","JsonValue":str(adj_r2)} + ] + ''' + return filepath,[hist['loss'],hist['val_loss'],[],[],hist['mae'],hist['val_mae'],hist['mse'],hist['val_mse']] def roc_auc_score_multiclass(actual_class, pred_class, average = "macro"): diff --git a/frontend/src/app/_data/Model.ts b/frontend/src/app/_data/Model.ts index 8fc36a31..f527dc7f 100644 --- a/frontend/src/app/_data/Model.ts +++ b/frontend/src/app/_data/Model.ts @@ -117,8 +117,8 @@ export enum ActivationFunctionOutputLayer export enum LossFunction { // binary classification loss functions BinaryCrossEntropy = 'binary_crossentropy', - SquaredHingeLoss = 'squared_hinge_loss', - HingeLoss = 'hinge_loss', + SquaredHingeLoss = 'squared_hinge', + HingeLoss = 'hinge', // multi-class classification loss functions CategoricalCrossEntropy = 'categorical_crossentropy', SparseCategoricalCrossEntropy = 'sparse_categorical_crossentropy', diff --git a/frontend/src/app/_data/Predictor.ts b/frontend/src/app/_data/Predictor.ts index c839a635..8de4cd17 100644 --- a/frontend/src/app/_data/Predictor.ts +++ b/frontend/src/app/_data/Predictor.ts @@ -13,8 +13,16 @@ export default class Predictor extends FolderFile { public experimentId: string = "", public modelId: string = "", public h5FileId: string = "", - public metrics: Metric[] = [], - public finalMetrics: Metric[] = [] + public metricsLoss:number[]=[], + public metricsValLoss:number []=[], + public metricsAcc:number[]=[], + public metricsValAcc: number[]=[], + public metricsMae :number []=[], + public metricsValMae :number []=[], + public metricsMse : number[]=[], + public metricsValMse : number[]=[], + //public metrics: Metric[] = [], + //public finalMetrics: Metric[] = [] ) { super(name, dateCreated, dateCreated); } diff --git a/frontend/src/app/_elements/column-table/column-table.component.css b/frontend/src/app/_elements/column-table/column-table.component.css index f7f07e62..311773f7 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.css +++ b/frontend/src/app/_elements/column-table/column-table.component.css @@ -22,7 +22,7 @@ table.fixed td { table.fixed th { overflow: hidden; - max-width: 120px; + max-width: 250px; min-width: 120px; vertical-align: middle; background-color: var(--ns-primary-50); diff --git a/frontend/src/app/_elements/column-table/column-table.component.html b/frontend/src/app/_elements/column-table/column-table.component.html index 31c32dfd..e6a781be 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.html +++ b/frontend/src/app/_elements/column-table/column-table.component.html @@ -35,7 +35,7 @@ </thead> <tbody> <tr *ngFor="let row of tableData; let i = index"> - <th>#{{i}}</th> + <th>#{{((this.begin/10)+1)*10-10+i+1}}</th> <td *ngFor="let col of row; let j = index" [ngClass]="{'text-disabled' : !columnsChecked[j]}"> <div class="text-overflow"> {{col}} @@ -200,7 +200,7 @@ </mat-menu> </div> <div *ngIf="colInfo.numNulls == 0" class="text-left"> - Nema null vrednosti. + Nema nedostajućih vrednosti. </div> </td> </tr> @@ -217,7 +217,7 @@ <div class="ns-col rounded"> <mat-form-field appearance="fill" class="align-items-center justify-content-center pt-3 w-100"> <mat-label>Izlazna kolona</mat-label> - <mat-select [(value)]="experiment.outputColumn" (selectionChange)="changeProblemType()"> + <mat-select [(value)]="experiment.outputColumn" (selectionChange)="outputColumnChanged()"> <mat-option *ngFor="let inputColumn of experiment.inputColumns" [value]="inputColumn">{{inputColumn}}</mat-option> <mat-option *ngIf="experiment.inputColumns.length == 0" value="-">-</mat-option> </mat-select> diff --git a/frontend/src/app/_elements/column-table/column-table.component.ts b/frontend/src/app/_elements/column-table/column-table.component.ts index ad78feaf..694b1a83 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.ts +++ b/frontend/src/app/_elements/column-table/column-table.component.ts @@ -131,6 +131,7 @@ export class ColumnTableComponent implements AfterViewInit { } else { this.dataset = dataset; + this.experimentChanged.emit(); this.columnsChecked = []; this.dataset.columnInfo.forEach(column => { if (this.experiment.inputColumns.find(x => x == column.columnName) != undefined) @@ -157,9 +158,6 @@ export class ColumnTableComponent implements AfterViewInit { this.resetPagging(); this.loadData(); this.loaded = true; - - this.updateCharts(); - this.updatePieChart(); } loadData(){ @@ -249,6 +247,19 @@ export class ColumnTableComponent implements AfterViewInit { } } + outputColumnChanged() { + let outputColReplacer = this.experiment.nullValuesReplacers.find(x => x.column == this.experiment.outputColumn); + let index = this.experiment.nullValuesReplacers.findIndex(x => x.column == this.experiment.outputColumn); + if (outputColReplacer != undefined) { + outputColReplacer.option = NullValueOptions.DeleteRows; + + let numOfRowsToDelete = (this.dataset!.columnInfo.filter(x => x.columnName == this.experiment.outputColumn)[0]).numNulls; + this.nullValOption[index] = "Obriši redove (" + numOfRowsToDelete + ")"; + } + + this.changeProblemType(); + } + changeProblemType() { if (this.experiment != undefined && this.dataset != undefined) { let i = this.dataset.columnInfo.findIndex(x => x.columnName == this.experiment!.outputColumn); @@ -300,14 +311,26 @@ export class ColumnTableComponent implements AfterViewInit { if (selectedMissingValuesOption == NullValueOptions.DeleteColumns) { this.experiment.nullValues = NullValueOptions.DeleteColumns; + + let outputColReplacer = this.experiment.nullValuesReplacers.find(x => x.column == this.experiment.outputColumn); + this.experiment.nullValuesReplacers = []; for (let i = 0; i < this.experiment.inputColumns.length; i++) { - this.experiment.nullValuesReplacers.push({ //ovo zakomentarisano - column: this.experiment.inputColumns[i], - option: NullValueOptions.DeleteColumns, - value: "" - }); - this.nullValOption[i] = "Obriši kolonu"; + if (this.experiment.inputColumns[i] != this.experiment.outputColumn) { + this.experiment.nullValuesReplacers.push({ //ovo zakomentarisano + column: this.experiment.inputColumns[i], + option: NullValueOptions.DeleteColumns, + value: "" + }); + this.nullValOption[i] = "Obriši kolonu"; + } + else { + if (outputColReplacer != undefined) { + this.experiment.nullValuesReplacers.push(outputColReplacer); + let numOfRowsToDelete = (this.dataset.columnInfo.filter(x => x.columnName == this.experiment!.inputColumns[i])[0]).numNulls; + this.nullValOption[i] = (outputColReplacer.option == NullValueOptions.DeleteRows) ? "Obriši redove (" + numOfRowsToDelete + ")" : "Popuni sa " + outputColReplacer.value + ""; + } + } } //obrisi kolone koje sadrze nedostajuce vrednosti iz input kolona /*for (let i = 0; i < this.dataset.columnInfo.length; i++) { @@ -336,7 +359,8 @@ export class ColumnTableComponent implements AfterViewInit { } openMissingValuesDialog() { const dialogRef = this.dialog.open(MissingvaluesDialogComponent, { - width: '500px' + width: '500px', + panelClass: 'custom-modalbox' }); dialogRef.afterClosed().subscribe(selectedMissingValuesOption => { if (selectedMissingValuesOption != undefined) diff --git a/frontend/src/app/_elements/folder/folder.component.css b/frontend/src/app/_elements/folder/folder.component.css index 4a06faa4..9e7644b6 100644 --- a/frontend/src/app/_elements/folder/folder.component.css +++ b/frontend/src/app/_elements/folder/folder.component.css @@ -182,8 +182,8 @@ .file-bottom-buttons { position: absolute; - bottom: 15px; - right: 15px; + bottom: 5px; + right: 4%; display: flex; flex-direction: row-reverse; } diff --git a/frontend/src/app/_elements/folder/folder.component.html b/frontend/src/app/_elements/folder/folder.component.html index 97ccc311..97ae0d23 100644 --- a/frontend/src/app/_elements/folder/folder.component.html +++ b/frontend/src/app/_elements/folder/folder.component.html @@ -57,10 +57,10 @@ <div class="file-content" [ngClass]="{'form-hidden' : listView}"> <div class="file-bottom-buttons" *ngIf="selectedTab != TabType.NewFile"> <button *ngIf="this.selectedFile && selectedTab == TabType.File" class="btn-clear file-button" (click)="deleteFile(this.selectedFile, $event)"> - <mat-icon>delete</mat-icon> + <mat-icon matTooltip="Obriši" matTooltipPosition="right">delete</mat-icon> </button> <button *ngIf="this.selectedFile && selectedTab==TabType.File && FolderType.Dataset==this.type" class="btn-clear file-button" (click)="downloadFile(this.selectedFile,$event)" style="display: inline-block;"> - <mat-icon>download</mat-icon> + <mat-icon matTooltip="Preuzmi" matTooltipPosition="before">download</mat-icon> </button> @@ -82,20 +82,20 @@ </div> <div class="mx-2 hover-show" *ngIf="selectedTab !== TabType.PublicDatasets && selectedTab !== TabType.PublicModels"> <button *ngIf="selectedTab==TabType.MyDatasets" class="btn-clear file-button" (click)="downloadFile(file,$event)" style="display: inline-block;"> - <mat-icon>download</mat-icon> + <mat-icon matTooltip="Preuzmi" matTooltipPosition="before">download</mat-icon> </button> <button class="btn-clear file-button" (click)="deleteFile(file, $event)" style="display: inline-block;"> - <mat-icon>delete</mat-icon> + <mat-icon matTooltip="Obriši" matTooltipPosition="right">delete</mat-icon> </button> </div> <div class="mx-2 hover-show" *ngIf="selectedTab == TabType.PublicDatasets || selectedTab == TabType.PublicModels"> <button class="btn-clear file-button" (click)="addFile(file, $event)"> - <mat-icon>note_add</mat-icon> + <mat-icon matTooltip="Uvezi" matTooltipPosition="right">note_add</mat-icon> </button> </div> </div> <div *ngIf="type == FolderType.Experiment" class="list-view"> - <div *ngFor="let predictor of predictorsForExp[file._id];" class="list-item"> + <div *ngFor="let predictor of predictorsForExp[file._id];" class="list-item" (click)="goToExperimentPageWithPredictor(file, predictor)"> <div class="mx-3"> <div class="f-row"> diff --git a/frontend/src/app/_elements/folder/folder.component.ts b/frontend/src/app/_elements/folder/folder.component.ts index f13635e9..254298fb 100644 --- a/frontend/src/app/_elements/folder/folder.component.ts +++ b/frontend/src/app/_elements/folder/folder.component.ts @@ -107,7 +107,7 @@ export class FolderComponent implements AfterViewInit { this.selectedFile = file; this.fileToDisplay = file; if (this.type == FolderType.Experiment && file) { - this.router.navigate(['/experiment/', file._id]); + this.router.navigate(['/experiment/' + file._id]); } this.newFileSelected = false; this.listView = false; @@ -118,12 +118,10 @@ export class FolderComponent implements AfterViewInit { if (this.type == FolderType.Dataset) this.formDataset.loadExisting(); } - /* - goToExperimentPage(file: FolderFile) { - console.log(<Experiment>file); - //this.router.navigate(['/experiment/', this.experiment._id]); + + goToExperimentPageWithPredictor(file: FolderFile, predictor: Predictor) { + this.router.navigate(['/experiment/' + file._id + "/" + predictor._id]); } - */ createNewFile() { if (this.type == FolderType.Dataset) { @@ -140,10 +138,7 @@ export class FolderComponent implements AfterViewInit { _initialized: boolean = false; refreshFiles(selectedDatasetId: string | null = null, selectedModelId: string | null = null) { - this.files = [] - this.filteredFiles.length = 0; - this.folders[TabType.NewFile] = []; - this.folders[TabType.File] = []; + this.tabsToShow.forEach(tab => { this.folders[tab] = []; }); @@ -203,6 +198,7 @@ export class FolderComponent implements AfterViewInit { refreshDatasets(selectedDatasetId: string | null) { this.datasetsService.getMyDatasets().subscribe((datasets) => { this.folders[TabType.MyDatasets] = datasets; + console.log(this.filteredFiles); if (selectedDatasetId) { this.selectFile(datasets.filter(x => x._id == selectedDatasetId)[0]); } @@ -239,7 +235,7 @@ export class FolderComponent implements AfterViewInit { case FolderType.Dataset: this.formDataset!.uploadDataset((dataset: Dataset) => { this.newFile = undefined; - Shared.openDialog("Obaveštenje", "Uspešno ste dodali novi izvor podataka u kolekciju. Molimo sačekajte par trenutaka da se procesira."); + Shared.openDialog("Obaveštenje", "Uspešno ste dodali novi izvor podataka u kolekciju. Molimo sačekajte par trenutaka da se obradi."); this.refreshFiles(); }, () => { @@ -288,17 +284,20 @@ export class FolderComponent implements AfterViewInit { deleteFile(file: FolderFile, event: Event) { event.stopPropagation(); - //console.log('delete'); + this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1); + this.files.splice(this.files.indexOf(file), 1); switch (this.type) { case FolderType.Dataset: this.datasetsService.deleteDataset(<Dataset>file).subscribe((response) => { - this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1); - this.refreshFiles(null); + Shared.openDialog("Obaveštenje", "Uspešno ste obrisali odabrani izvor podataka."); + //this.filteredFiles.splice(this.files.indexOf(file), 1); + //this.refreshFiles(); }); break; case FolderType.Model: this.modelsService.deleteModel(<Model>file).subscribe((response) => { - this.refreshFiles(null); + Shared.openDialog("Obaveštenje", "Uspešno ste obrisali odabranu konfiguraciju neuronske mreže."); + //this.refreshFiles(); }); break; case FolderType.Experiment: @@ -332,13 +331,22 @@ export class FolderComponent implements AfterViewInit { (<Dataset>file).isPreProcess = true; (<Dataset>file).isPublic = false; this.datasetsService.stealDataset(<Dataset>file).subscribe((response) => { - this.filteredFiles.splice(this.filteredFiles.indexOf(file), 1); + Shared.openDialog("Obaveštenje", "Uspešno ste dodali javni izvor podataka u vašu kolekciju."); this.refreshFiles(null); + }, (error:any) => { + if (error.error == "Dataset with this name already exists") { + Shared.openDialog("Obaveštenje", "Izvor podataka sa ovim imenom postoji u vašoj kolekciji."); + } }); break; case FolderType.Model: - this.modelsService.addModel(<Model>file).subscribe((response) => { + this.modelsService.stealModel(<Model>file).subscribe((response) => { + Shared.openDialog("Obaveštenje", "Uspešno ste dodali javnu konfiguraciju neuronske mreže u vašu kolekciju."); this.refreshFiles(null); + }, (error:any) => { + if (error.error == "Model already exisits or validation size is not between 0-1") { + Shared.openDialog("Obaveštenje", "Model sa ovim imenom postoji u vašoj kolekciji."); + } }); break; case FolderType.Experiment: diff --git a/frontend/src/app/_elements/form-model/form-model.component.ts b/frontend/src/app/_elements/form-model/form-model.component.ts index c9e2fc8e..9e6082c4 100644 --- a/frontend/src/app/_elements/form-model/form-model.component.ts +++ b/frontend/src/app/_elements/form-model/form-model.component.ts @@ -84,7 +84,7 @@ export class FormModelComponent implements AfterViewInit { } addLayer() { - if (this.newModel.hiddenLayers < 128) { + if (this.newModel.hiddenLayers < 150) { this.newModel.layers.push(new Layer(this.newModel.layers.length, this.selectedActivation, this.selectedNumberOfNeurons, this.selectedRegularisation, this.selectedRegularisationRate)); this.newModel.hiddenLayers += 1; diff --git a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.html b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.html index 2d7e4d86..84793260 100644 --- a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.html +++ b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.html @@ -1,9 +1,9 @@ - - - <h2 mat-dialog-title >{{data.title}}</h2> - <div mat-dialog-content class="mt-4 text-offwhite" > - {{data.message}} - </div> - <div mat-dialog-actions class="d-flex justify-content-center mt-4"> +<h2 mat-dialog-title>{{data.title}}</h2> +<div mat-dialog-content class="mt-4 text-offwhite"> + <form (keydown)="withEnterKey($event)"> + {{data.message}} + </form> +</div> +<div mat-dialog-actions class="d-flex justify-content-center mt-4"> <button mat-raised-button cdkFocusInitial (click)="onOkClick()" color="basic">OK</button> - </div>
\ No newline at end of file +</div>
\ No newline at end of file diff --git a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts index e15f3c6f..7558b527 100644 --- a/frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts +++ b/frontend/src/app/_modals/alert-dialog/alert-dialog.component.ts @@ -20,9 +20,11 @@ export class AlertDialogComponent { //public dialog: MatDialog ) {} + withEnterKey(keyboardEvent: KeyboardEvent) { + if (keyboardEvent.code == "Enter" || keyboardEvent.code == "NumpadEnter") + this.onOkClick(); + } onOkClick(): void { this.dialogRef.close(); } - - } diff --git a/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html index 08c1f26b..fed8f8d7 100644 --- a/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html +++ b/frontend/src/app/_modals/encoding-dialog/encoding-dialog.component.html @@ -1,15 +1,17 @@ <h2 mat-dialog-title class="text-center">Enkodiranje svih kolona</h2> <div mat-dialog-content class="mt-5 mb-4"> <p>Sve izabrane kolone biće enkodirane metodom:</p> - <form (keydown)="withEnterKey($event)"> - <mat-form-field> - <mat-select matNativeControl [(value)]="selectedEncodingType" cdkFocusInitial> - <mat-option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" [value]="option"> - {{ optionName }} - </mat-option> - </mat-select> - </mat-form-field> - </form> + <div class="d-flex justify-content-center"> + <form (keydown)="withEnterKey($event)"> + <mat-form-field> + <mat-select matNativeControl [(value)]="selectedEncodingType" cdkFocusInitial> + <mat-option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" [value]="option"> + {{ optionName }} + </mat-option> + </mat-select> + </mat-form-field> + </form> + </div> </div> <div mat-dialog-actions class="justify-content-center"> <button id="btnYes" mat-stroked-button color="basic" (click)="onYesClick()">Potvrdi</button> diff --git a/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css index e99a1e1e..64d7bd21 100644 --- a/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css +++ b/frontend/src/app/_modals/missingvalues-dialog/missingvalues-dialog.component.css @@ -5,4 +5,8 @@ #btnNo { color: gray; +} + +::ng-deep.mat-dialog-content { + overflow: visible; }
\ No newline at end of file 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 index 06e74093..77e7be42 100644 --- 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 @@ -1,8 +1,10 @@ <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}} + <form (keydown)="withEnterKey($event)"> + {{data.message}} + </form> </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> + <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.ts b/frontend/src/app/_modals/yes-no-dialog/yes-no-dialog.component.ts index de1cdd4f..a7db1e7f 100644 --- 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 @@ -24,10 +24,13 @@ export class YesNoDialogComponent { onNoClick(): void { this.dialogRef.close(); } - onYesClick():void{ + + withEnterKey(keyboardEvent: KeyboardEvent) { + if (keyboardEvent.code == "Enter" || keyboardEvent.code == "NumpadEnter") + this.onYesClick(); + } + onYesClick():void { this.data.yesFunction(); this.dialogRef.close(); } - - } diff --git a/frontend/src/app/_pages/experiment/experiment.component.css b/frontend/src/app/_pages/experiment/experiment.component.css index 2298ae48..59e004e9 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.css +++ b/frontend/src/app/_pages/experiment/experiment.component.css @@ -48,6 +48,7 @@ mat-stepper { flex-direction: row; justify-content: center; align-items: center; + /*margin-bottom: 100px;*/ } .step-content-inside { @@ -66,4 +67,11 @@ mat-stepper { .text-overflow { overflow-wrap: break-word; + width: 170px; + display: inline-block; + text-align: left; +} + +.text-overflow-experiment-name { + overflow-wrap: break-word; }
\ No newline at end of file diff --git a/frontend/src/app/_pages/experiment/experiment.component.html b/frontend/src/app/_pages/experiment/experiment.component.html index 8f462f86..e807dd06 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.html +++ b/frontend/src/app/_pages/experiment/experiment.component.html @@ -2,10 +2,10 @@ <div class="d-flex flex-colum align-items-center sidenav"> <div> <div class="ekspName " style="width: 250px;"> - <div class="text-overflow" *ngIf="experiment.name=='exp1'" style="width: 250px;"> + <div class="text-overflow-experiment-name" *ngIf="experiment.name=='exp1'" style="width: 250px;"> Novi Eksperiment </div> - <div class="text-overflow" *ngIf="experiment.name!='exp1'" style="width: 250px;"> + <div class="text-overflow-experiment-name" *ngIf="experiment.name!='exp1'" style="width: 250px;"> {{experiment.name}} </div> @@ -14,37 +14,37 @@ <mat-step [completed]="this.step1"> <!--editable="false"--> <ng-template matStepLabel> - <span class="label" *ngIf="dataset==undefined">Izvor podataka </span> - <span class="label addedElement" *ngIf="dataset!=undefined">{{dataset.name}}</span> + <span class="label text-overflow" *ngIf="dataset==undefined">Izvor podataka </span> + <span class="label addedElement text-overflow" *ngIf="dataset!=undefined">{{dataset.name}}</span> </ng-template> <ng-template matStepContent> - <p class="text-left">Izaberite izvor podataka</p> + <p class="text-left text-overflow">Izaberite izvor podataka</p> </ng-template> </mat-step> <mat-step [completed]="experiment._id!=''"> <ng-template matStepLabel> - <span class="label addedElement" *ngIf="experiment._id!=''">Predvideti:{{experiment.outputColumn}}</span> + <span class="label addedElement text-overflow" *ngIf="experiment._id!=''">Predvideti:{{experiment.outputColumn}}</span> <span *ngIf="!this.step1" class="align-middle"><mat-icon>lock</mat-icon></span> - <span class="label" *ngIf="experiment._id==''">Odabir kolona </span> + <span class="label text-overflow" *ngIf="experiment._id==''">Odabir kolona </span> </ng-template> <ng-template matStepContent> - <p class="text-left">Pripremite podatke i izaberite izlazne kolone</p> + <p class="text-left text-overflow">Pripremite podatke i izaberite izlazne kolone</p> </ng-template> </mat-step> <mat-step [completed]="this.step3"> <ng-template matStepLabel> <span *ngIf="experiment._id==''" class="align-middle"><mat-icon>lock</mat-icon></span> - <span class="label addedElement" *ngIf="modelToTrain!=undefined">{{modelToTrain.name}}</span> - <span class="label" *ngIf="modelToTrain==undefined">Treniranje</span> + <span class="label addedElement text-overflow" *ngIf="modelToTrain!=undefined">{{modelToTrain.name}}</span> + <span class="label text-overflow" *ngIf="modelToTrain==undefined">Treniranje</span> </ng-template> - <p class="text-left">Odaberite parametre i trenirajte model</p> + <p class="text-left text-overflow">Odaberite parametre i trenirajte model</p> </mat-step> <mat-step [completed]="this.step4"> <ng-template matStepLabel> <span *ngIf="!this.step3" class="align-middle"><mat-icon>lock</mat-icon></span> - <span class="label">Pregled rezultata<br> treniranja</span> + <span class="label text-overflow">Pregled rezultata<br> treniranja</span> </ng-template> - <p class="text-left">Pregledajte tok treniranja i<br> grafički prikaz rezultata</p> + <p class="text-left text-overflow">Pregledajte tok treniranja i<br> grafički prikaz rezultata</p> </mat-step> </mat-stepper> </div> diff --git a/frontend/src/app/_pages/experiment/experiment.component.ts b/frontend/src/app/_pages/experiment/experiment.component.ts index 312b1af1..6c8e96b3 100644 --- a/frontend/src/app/_pages/experiment/experiment.component.ts +++ b/frontend/src/app/_pages/experiment/experiment.component.ts @@ -14,6 +14,7 @@ import { SignalRService } from 'src/app/_services/signal-r.service'; import { MetricViewComponent } from 'src/app/_elements/metric-view/metric-view.component'; import { ActivatedRoute, Router } from '@angular/router'; import { DatasetsService } from 'src/app/_services/datasets.service'; +import { PredictorsService } from 'src/app/_services/predictors.service'; @Component({ selector: 'app-experiment', @@ -39,24 +40,47 @@ export class ExperimentComponent implements AfterViewInit, OnInit { step3: boolean = false; step4: boolean = false; - constructor(private experimentsService: ExperimentsService, private modelsService: ModelsService, private datasetsService: DatasetsService, private signalRService: SignalRService, private route: ActivatedRoute) { + constructor(private experimentsService: ExperimentsService, private modelsService: ModelsService, private datasetsService: DatasetsService, private predictorsService: PredictorsService, private signalRService: SignalRService, private route: ActivatedRoute) { this.experiment = new Experiment("exp1"); } ngOnInit(): void { this.route.queryParams.subscribe(params => { + let experimentId = this.route.snapshot.paramMap.get("id"); - if (experimentId == null) - return; - this.experimentsService.getExperimentById(experimentId).subscribe((response) => { - this.experiment = response; - this.datasetsService.getDatasetById(this.experiment.datasetId).subscribe((response: Dataset) => { - this.dataset = response; - - this.folderDataset.forExperiment = this.experiment; - this.folderDataset.selectFile(this.dataset); + let predictorId = this.route.snapshot.paramMap.get("predictorId"); + + if (predictorId != null && experimentId != null) { + this.experimentsService.getExperimentById(experimentId).subscribe((response) => { + this.experiment = response; + this.datasetsService.getDatasetById(this.experiment.datasetId).subscribe((response: Dataset) => { + this.dataset = response; + this.folderDataset.forExperiment = this.experiment; + this.folderDataset.selectFile(this.dataset); //sad 3. i 4. korak da se ucitaju + + //this.predictorsService.getPredictor(predictorId!).subscribe((response) => { + let predictor = response; + //this.modelsService.getModelById(predictor.modelId).subscribe((response) => { + this.modelsService.getModelById("62853d70696d62ceeb8db7cd").subscribe((response) => { + //imamo model + this.folderModel.formModel.newModel = response; + //this.metricView.update(predictor.metrics); + }); + //}); + }); }); - }); + } + else if (predictorId == null && experimentId != null) { + this.experimentsService.getExperimentById(experimentId).subscribe((response) => { + this.experiment = response; + this.datasetsService.getDatasetById(this.experiment.datasetId).subscribe((response: Dataset) => { + this.dataset = response; + this.folderDataset.forExperiment = this.experiment; + this.folderDataset.selectFile(this.dataset); + }); + }); + } + }); } diff --git a/frontend/src/app/_services/models.service.ts b/frontend/src/app/_services/models.service.ts index fc888556..f5d95ec1 100644 --- a/frontend/src/app/_services/models.service.ts +++ b/frontend/src/app/_services/models.service.ts @@ -31,6 +31,10 @@ export class ModelsService { addModel(model: Model): Observable<any> { return this.http.post(`${Configuration.settings.apiURL}/model/add`, model, { headers: this.authService.authHeader() }); } + + stealModel(model: Model): Observable<any> { + return this.http.post(`${Configuration.settings.apiURL}/model/stealModel`, model, { headers: this.authService.authHeader() }); + } addDataset(dataset: Dataset): Observable<any> { return this.http.post(`${Configuration.settings.apiURL}/dataset/add`, dataset, { headers: this.authService.authHeader() }); } @@ -58,4 +62,8 @@ export class ModelsService { return this.http.get<Model[]>(`${Configuration.settings.apiURL}/model/publicmodels`, { headers: this.authService.authHeader() }); } + getModelById(modelId: string): Observable<Model> { + return this.http.get<Model>(`${Configuration.settings.apiURL}/model/byid/${modelId}`, { headers: this.authService.authHeader() }); + } + } diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 9f8c623d..56442842 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -12,12 +12,14 @@ import { TestComponent } from './_pages/test/test.component'; const routes: Routes = [ { path: '', component: HomeComponent, data: { title: 'Početna strana' } }, + { path: 'experiment/:id/:predictorId', component: ExperimentComponent, data: { title: 'Eksperiment' } }, { path: 'experiment/:id', component: ExperimentComponent, data: { title: 'Eksperiment' } }, { path: 'experiment', component: ExperimentComponent, data: { title: 'Eksperiment' } }, { path: 'archive', component: ArchiveComponent, data: { title: 'Arhiva' } }, { path: 'profile', component: ProfileComponent, canActivate: [AuthGuardService], data: { title: 'Profil' } }, { path: 'playground', component: PlaygroundComponent, data: { title: 'Zabava' } }, - { path: 'test', component: TestComponent, data: { title: 'Test' } } + { path: 'test', component: TestComponent, data: { title: 'Test' } }, + { path: '**', redirectTo: '' } ]; @NgModule({ |