aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanijel Andjelkovic <adanijel99@gmail.com>2022-03-30 12:41:53 +0200
committerDanijel Andjelkovic <adanijel99@gmail.com>2022-03-30 12:41:53 +0200
commitad9193d35e5ae2f6847492f1867963fc1672ee3e (patch)
treebe3b3a54bc42696e73f3c3092a9f52db8355c07f
parent6af8655c2d1a24c0c3ba851bb28d72f9d06c83b0 (diff)
parent476393d1530b261b8a145db2533262979558e064 (diff)
Merge branch 'dev' of http://gitlab.pmf.kg.ac.rs/igrannonica/neuronstellar into dev
-rw-r--r--backend/api/api/Controllers/DatasetController.cs5
-rw-r--r--backend/api/api/Controllers/ModelController.cs2
-rw-r--r--backend/api/api/Controllers/PredictorController.cs30
-rw-r--r--backend/api/api/Controllers/UserController.cs3
-rw-r--r--backend/api/api/Services/DatasetService.cs7
-rw-r--r--backend/api/api/Services/IDatasetService.cs1
-rw-r--r--backend/api/api/Services/IPredictorService.cs1
-rw-r--r--backend/api/api/Services/IUserService.cs2
-rw-r--r--backend/api/api/Services/PredictorService.cs5
-rw-r--r--backend/api/api/Services/UserService.cs51
-rw-r--r--backend/microservice/regression.py53
-rw-r--r--backend/microservice/regressionFCNN.ipynb595
-rw-r--r--frontend/src/app/_data/Model.ts10
-rw-r--r--frontend/src/app/_elements/annvisual/annvisual.component.ts13
-rw-r--r--frontend/src/app/_pages/add-model/add-model.component.html46
-rw-r--r--frontend/src/app/_pages/add-model/add-model.component.ts119
-rw-r--r--frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts9
-rw-r--r--frontend/src/app/_pages/my-models/my-models.component.html1
-rw-r--r--frontend/src/app/_services/auth.service.ts39
-rw-r--r--frontend/src/app/_services/csv-parse.service.ts3
-rw-r--r--frontend/src/app/app.component.ts7
-rw-r--r--frontend/src/app/app.module.ts4
22 files changed, 376 insertions, 630 deletions
diff --git a/backend/api/api/Controllers/DatasetController.cs b/backend/api/api/Controllers/DatasetController.cs
index bae05ba9..d9803744 100644
--- a/backend/api/api/Controllers/DatasetController.cs
+++ b/backend/api/api/Controllers/DatasetController.cs
@@ -24,7 +24,7 @@ namespace api.Controllers
// GET: api/<DatasetController>/mydatasets
[HttpGet("mydatasets")]
- [Authorize(Roles = "User")]
+ [Authorize(Roles = "User,Guest")]
public ActionResult<List<Dataset>> Get()
{
string username;
@@ -39,6 +39,9 @@ namespace api.Controllers
}
else
return BadRequest();
+ //U slucaju da je korisnik gost vrati dataSetove igrannonice
+ if (username == "")
+ return _datasetService.GetGuestDatasets();
//ako bude trebao ID, samo iz baze uzeti
diff --git a/backend/api/api/Controllers/ModelController.cs b/backend/api/api/Controllers/ModelController.cs
index 4bc094cd..355eb9f4 100644
--- a/backend/api/api/Controllers/ModelController.cs
+++ b/backend/api/api/Controllers/ModelController.cs
@@ -30,7 +30,7 @@ namespace api.Controllers
}
[HttpPost("sendModel")]
- [Authorize(Roles = "User")]
+ [Authorize(Roles = "User,Guest")]
public async Task<ActionResult<string>> Test([FromBody] Model model)
{
var dataset = _datasetService.GetOneDataset(model.datasetId);
diff --git a/backend/api/api/Controllers/PredictorController.cs b/backend/api/api/Controllers/PredictorController.cs
index 7f8f1692..63c5d2bf 100644
--- a/backend/api/api/Controllers/PredictorController.cs
+++ b/backend/api/api/Controllers/PredictorController.cs
@@ -74,6 +74,36 @@ namespace api.Controllers
return _predictorService.SearchPredictors(name, username);
}
+ //SEARCH za predictore (public ili private sa ovim imenom )
+ // GET api/<PredictorController>/search/{name}
+ [HttpGet("{id}")]
+ [Authorize(Roles = "User")]
+ public ActionResult<Predictor> GetPredictor(string id)
+ {
+ string username;
+ var header = Request.Headers[HeaderNames.Authorization];
+ if (AuthenticationHeaderValue.TryParse(header, out var headerValue))
+ {
+ var scheme = headerValue.Scheme;
+ var parameter = headerValue.Parameter;
+ username = jwtToken.TokenToUsername(parameter);
+ if (username == null)
+ return null;
+ }
+ else
+ return BadRequest();
+
+ //ako bude trebao ID, samo iz baze uzeti
+
+ Predictor predictor = _predictorService.GetPredictor(username, id);
+
+ if (predictor == null)
+ return NotFound($"Predictor with id = {id} not found");
+
+ return predictor;
+ }
+
+
//da li da se odvoji search za public i posebno za private?
// GET api/<PredictorController>/{name}
[HttpGet("{name}")]
diff --git a/backend/api/api/Controllers/UserController.cs b/backend/api/api/Controllers/UserController.cs
index 0287f3cb..741382b8 100644
--- a/backend/api/api/Controllers/UserController.cs
+++ b/backend/api/api/Controllers/UserController.cs
@@ -135,8 +135,7 @@ namespace api.Controllers
else
return BadRequest();
- userService.Update(username, user);
- return NoContent();
+ return Ok(userService.Update(username, user));
}
// DELETE api/<UserController>/5
diff --git a/backend/api/api/Services/DatasetService.cs b/backend/api/api/Services/DatasetService.cs
index 45ed18a9..2ff271f3 100644
--- a/backend/api/api/Services/DatasetService.cs
+++ b/backend/api/api/Services/DatasetService.cs
@@ -36,6 +36,13 @@ namespace api.Services
{
return _dataset.Find(dataset => dataset.username == username).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).ToList();
+ datasets.AddRange(_dataset.Find(dataset => dataset.username == "").ToList());
+ return datasets;
+ }
//poslednji datasetovi
public List<Dataset> SortDatasets(string username, bool ascdsc, int latest)
diff --git a/backend/api/api/Services/IDatasetService.cs b/backend/api/api/Services/IDatasetService.cs
index dbe43321..8e62ba43 100644
--- a/backend/api/api/Services/IDatasetService.cs
+++ b/backend/api/api/Services/IDatasetService.cs
@@ -14,5 +14,6 @@ namespace api.Services
Dataset Create(Dataset dataset);
void Update(string username, string name, Dataset dataset);
void Delete(string username, string name);
+ public List<Dataset> GetGuestDatasets();
}
}
diff --git a/backend/api/api/Services/IPredictorService.cs b/backend/api/api/Services/IPredictorService.cs
index 2017add2..729dd0b6 100644
--- a/backend/api/api/Services/IPredictorService.cs
+++ b/backend/api/api/Services/IPredictorService.cs
@@ -6,6 +6,7 @@ namespace api.Services
public interface IPredictorService
{
Predictor GetOnePredictor(string username, string name);
+ Predictor GetPredictor(string username, string GetPredictor);
List<Predictor> SearchPredictors(string name, string username);
List<Predictor> GetMyPredictors(string username);
List<Predictor> SortPredictors(string username, bool ascdsc, int latest);
diff --git a/backend/api/api/Services/IUserService.cs b/backend/api/api/Services/IUserService.cs
index 1cb6a609..e4a23213 100644
--- a/backend/api/api/Services/IUserService.cs
+++ b/backend/api/api/Services/IUserService.cs
@@ -8,7 +8,7 @@ namespace api.Services
List<User> Get();// daje sve korisnike
User GetUserUsername(string username); //daje korisnika po korisnickom imenu
User Create(User user); // kreira korisnika
- void Update(string username, User user); //apdejtuje korisnika po idu
+ bool Update(string username, User user); //apdejtuje korisnika po idu
void Delete(string username);//brise korisnika
}
}
diff --git a/backend/api/api/Services/PredictorService.cs b/backend/api/api/Services/PredictorService.cs
index 05860126..01bc8359 100644
--- a/backend/api/api/Services/PredictorService.cs
+++ b/backend/api/api/Services/PredictorService.cs
@@ -40,6 +40,11 @@ namespace api.Services
return _predictor.Find(predictor => predictor.username == username && predictor.name == name).FirstOrDefault();
}
+ public Predictor GetPredictor(string username, string id)
+ {
+ return _predictor.Find(predictor => predictor.username == username && predictor._id == id).FirstOrDefault();
+
+ }
//last private models
public List<Predictor> SortPredictors(string username, bool ascdsc, int latest)
{
diff --git a/backend/api/api/Services/UserService.cs b/backend/api/api/Services/UserService.cs
index f613f923..607bb04b 100644
--- a/backend/api/api/Services/UserService.cs
+++ b/backend/api/api/Services/UserService.cs
@@ -7,11 +7,22 @@ namespace api.Services
public class UserService : IUserService
{
private readonly IMongoCollection<User> _users;
+ private readonly IMongoClient _client;
+ private readonly IMongoCollection<Model> _models;
+ private readonly IMongoCollection<Dataset> _datasets;
+ private readonly IMongoCollection<FileModel> _fileModels;
+ private readonly IMongoCollection<Predictor> _predictors;
+
public UserService(IUserStoreDatabaseSettings settings, IMongoClient mongoClient)
{
var database = mongoClient.GetDatabase(settings.DatabaseName);
_users = database.GetCollection<User>(settings.CollectionName);
+ _models = database.GetCollection<Model>(settings.ModelCollectionName);
+ _datasets= database.GetCollection<Dataset>(settings.DatasetCollectionName);
+ _fileModels = database.GetCollection<FileModel>(settings.FilesCollectionName);
+ _predictors= database.GetCollection<Predictor>(settings.PredictorCollectionName);
+ _client = mongoClient;
}
public User Create(User user)
{
@@ -26,10 +37,46 @@ namespace api.Services
{
return _users.Find(user => user.Username == username).FirstOrDefault();
}
- public void Update(string username, User user)
+ public bool Update(string username, User user)
{
//username koji postoji u bazi
- _users.ReplaceOne(user => user.Username == username, user);
+ using (var session = _client.StartSession())
+ {
+
+ 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)
+ {
+ var builderModel = Builders<Model>.Update;
+ var builderDataset = Builders<Dataset>.Update;
+ var builderFileModel = Builders<FileModel>.Update;
+ var builderPredictor = Builders<Predictor>.Update;
+ _models.UpdateMany(x => x.username == username, builderModel.Set(x => x.username, user.Username));
+ _datasets.UpdateMany(x => x.username == username, builderDataset.Set(x => x.username, user.Username));
+ _fileModels.UpdateMany(x => x.username == username, builderFileModel.Set(x => x.username, user.Username));
+ _predictors.UpdateMany(x => x.username == username, builderPredictor.Set(x => x.username, user.Username));
+ }
+
+ //session.AbortTransaction();
+
+
+ //session.CommitTransaction();
+ }
+ catch (Exception e)
+ {
+ //session.AbortTransaction();
+ return false;
+ }
+ return true;
+ }
}
public void Delete(string username)
{
diff --git a/backend/microservice/regression.py b/backend/microservice/regression.py
new file mode 100644
index 00000000..f039292c
--- /dev/null
+++ b/backend/microservice/regression.py
@@ -0,0 +1,53 @@
+import numpy as np
+from tensorflow.keras.datasets import boston_housing
+from sklearn.preprocessing import StandardScaler
+from tensorflow.keras.models import load_model
+
+x_new = np.random.rand(X_train.shape[1])
+x_new = x_new.reshape(1,-1)
+# x_new.shape
+y_pred = model.predict(x_new)
+if y_pred < 0.5:
+ print('0')
+else:
+ print('1')
+
+(X_train, y_train), (X_test, y_test) = boston_housing.load_data()
+
+X_train.shape
+X_test.shape
+X_train[0]
+y_test
+
+scaler = StandardScaler()
+scaler.fit(X_train)
+X_train = scaler.transform(X_train)
+X_test = scaler.transform(X_test)
+
+X_train[0]
+X_test
+
+model = Sequential()
+model.add(Dense(input_dim=X_train.shape[1], units=100, activation='relu'))
+# model.add(Dense(input_dim=X_train.shape[1], units=50, activation='relu'))
+model.add(Dense(units=1))
+model.summary()
+
+model.compile(optimizer='adam', loss='mse', metrics=['mae'])
+history = model.fit(X_train, y_train, batch_size=32, epochs=20, validation_split=0.2)
+
+plt.plot(history.epoch, history.history['loss'])
+plt.plot(history.epoch, history.history['val_loss'])
+
+plt.plot(history.epoch, history.history['mae'])
+plt.plot(history.epoch, history.history['val_mae'])
+
+model.evaluate(X_test, y_test)
+model.save('models/boston.h5')
+old_model = load_model('models/boston.h5')
+
+x_new = np.random.rand(X_train.shape[1])
+x_new = x_new.reshape(1, -1)
+x_new.shape
+# Za nove podatke koristi se predict tako da se dobije predvidjena vrednost za y
+old_model.predict(x_new) \ No newline at end of file
diff --git a/backend/microservice/regressionFCNN.ipynb b/backend/microservice/regressionFCNN.ipynb
deleted file mode 100644
index 470a9831..00000000
--- a/backend/microservice/regressionFCNN.ipynb
+++ /dev/null
@@ -1,595 +0,0 @@
-{
- "nbformat": 4,
- "nbformat_minor": 0,
- "metadata": {
- "colab": {
- "name": "regressionFCNN.ipynb",
- "provenance": [],
- "collapsed_sections": []
- },
- "kernelspec": {
- "name": "python3",
- "display_name": "Python 3"
- },
- "language_info": {
- "name": "python"
- },
- "accelerator": "GPU"
- },
- "cells": [
- {
- "cell_type": "markdown",
- "source": [
- "Dataset - Boston Housing"
- ],
- "metadata": {
- "id": "8vzWlOHFi6el"
- }
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "id": "OnfiK4W-g9NC"
- },
- "outputs": [],
- "source": [
- "import numpy as np"
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "from tensorflow.keras.datasets import boston_housing"
- ],
- "metadata": {
- "id": "f_siGNjyhNG4"
- },
- "execution_count": 4,
- "outputs": []
- },
- {
- "cell_type": "code",
- "source": [
- "(X_train, y_train), (X_test, y_test) = boston_housing.load_data()"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "v6rzMZSahNEp",
- "outputId": "b6f076c9-e69a-42b6-b1ca-d2c942efb684"
- },
- "execution_count": 5,
- "outputs": [
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/boston_housing.npz\n",
- "57344/57026 [==============================] - 0s 0us/step\n",
- "65536/57026 [==================================] - 0s 0us/step\n"
- ]
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "X_train.shape"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "wJDkN70phNB5",
- "outputId": "fef03e1d-595f-4e0c-9e48-cac1b7cf0c66"
- },
- "execution_count": 6,
- "outputs": [
- {
- "output_type": "execute_result",
- "data": {
- "text/plain": [
- "(404, 13)"
- ]
- },
- "metadata": {},
- "execution_count": 6
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "X_test.shape"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "sZCvrECthM--",
- "outputId": "c1b12abe-13d5-4b46-a67e-90aa7b613b4f"
- },
- "execution_count": 7,
- "outputs": [
- {
- "output_type": "execute_result",
- "data": {
- "text/plain": [
- "(102, 13)"
- ]
- },
- "metadata": {},
- "execution_count": 7
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "X_train[0]"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "9i8Ix3ZkhM8U",
- "outputId": "1be03f2d-faf3-4856-9eb7-bc550d77c91e"
- },
- "execution_count": 8,
- "outputs": [
- {
- "output_type": "execute_result",
- "data": {
- "text/plain": [
- "array([ 1.23247, 0. , 8.14 , 0. , 0.538 , 6.142 ,\n",
- " 91.7 , 3.9769 , 4. , 307. , 21. , 396.9 ,\n",
- " 18.72 ])"
- ]
- },
- "metadata": {},
- "execution_count": 8
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "y_test"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "1a-jNd6KhM5a",
- "outputId": "a54ce6e6-6462-4a0f-99c1-c13ebc47844a"
- },
- "execution_count": 9,
- "outputs": [
- {
- "output_type": "execute_result",
- "data": {
- "text/plain": [
- "array([ 7.2, 18.8, 19. , 27. , 22.2, 24.5, 31.2, 22.9, 20.5, 23.2, 18.6,\n",
- " 14.5, 17.8, 50. , 20.8, 24.3, 24.2, 19.8, 19.1, 22.7, 12. , 10.2,\n",
- " 20. , 18.5, 20.9, 23. , 27.5, 30.1, 9.5, 22. , 21.2, 14.1, 33.1,\n",
- " 23.4, 20.1, 7.4, 15.4, 23.8, 20.1, 24.5, 33. , 28.4, 14.1, 46.7,\n",
- " 32.5, 29.6, 28.4, 19.8, 20.2, 25. , 35.4, 20.3, 9.7, 14.5, 34.9,\n",
- " 26.6, 7.2, 50. , 32.4, 21.6, 29.8, 13.1, 27.5, 21.2, 23.1, 21.9,\n",
- " 13. , 23.2, 8.1, 5.6, 21.7, 29.6, 19.6, 7. , 26.4, 18.9, 20.9,\n",
- " 28.1, 35.4, 10.2, 24.3, 43.1, 17.6, 15.4, 16.2, 27.1, 21.4, 21.5,\n",
- " 22.4, 25. , 16.6, 18.6, 22. , 42.8, 35.1, 21.5, 36. , 21.9, 24.1,\n",
- " 50. , 26.7, 25. ])"
- ]
- },
- "metadata": {},
- "execution_count": 9
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "from sklearn.preprocessing import StandardScaler"
- ],
- "metadata": {
- "id": "c9ETzZu-hMzb"
- },
- "execution_count": 10,
- "outputs": []
- },
- {
- "cell_type": "code",
- "source": [
- "scaler = StandardScaler()\n",
- "scaler.fit(X_train)\n",
- "X_train = scaler.transform(X_train)\n",
- "X_test = scaler.transform(X_test)"
- ],
- "metadata": {
- "id": "VUb0qQR7hepF"
- },
- "execution_count": 11,
- "outputs": []
- },
- {
- "cell_type": "code",
- "source": [
- "X_train[0]"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "Qhjccz_whemx",
- "outputId": "083f4f0b-1295-43c9-b6ac-2160f909dc50"
- },
- "execution_count": 12,
- "outputs": [
- {
- "output_type": "execute_result",
- "data": {
- "text/plain": [
- "array([-0.27224633, -0.48361547, -0.43576161, -0.25683275, -0.1652266 ,\n",
- " -0.1764426 , 0.81306188, 0.1166983 , -0.62624905, -0.59517003,\n",
- " 1.14850044, 0.44807713, 0.8252202 ])"
- ]
- },
- "metadata": {},
- "execution_count": 12
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "X_test"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "lQcbYns7hejc",
- "outputId": "32eccf17-3220-44f8-bfa7-ae6300a3f41e"
- },
- "execution_count": 13,
- "outputs": [
- {
- "output_type": "execute_result",
- "data": {
- "text/plain": [
- "array([[ 1.55369355, -0.48361547, 1.0283258 , ..., 0.78447637,\n",
- " -3.48459553, 2.25092074],\n",
- " [-0.39242675, -0.48361547, -0.16087773, ..., -0.30759583,\n",
- " 0.42733126, 0.47880119],\n",
- " [-0.39982927, -0.48361547, -0.86940196, ..., 0.78447637,\n",
- " 0.44807713, -0.41415936],\n",
- " ...,\n",
- " [-0.20709507, -0.48361547, 1.24588095, ..., -1.71818909,\n",
- " 0.37051949, -1.49344089],\n",
- " [-0.36698601, -0.48361547, -0.72093526, ..., -0.48960787,\n",
- " 0.39275481, -0.41829982],\n",
- " [-0.0889679 , -0.48361547, 1.24588095, ..., -1.71818909,\n",
- " -1.21946544, -0.40449827]])"
- ]
- },
- "metadata": {},
- "execution_count": 13
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "from tensorflow.keras.models import Sequential\n",
- "from tensorflow.keras.layers import Dense"
- ],
- "metadata": {
- "id": "WbQA9y9BioPi"
- },
- "execution_count": 15,
- "outputs": []
- },
- {
- "cell_type": "code",
- "source": [
- "model = Sequential()\n",
- "model.add(Dense(input_dim=X_train.shape[1], units=100, activation='relu'))\n",
- "# model.add(Dense(input_dim=X_train.shape[1], units=50, activation='relu'))\n",
- "model.add(Dense(units=1))\n",
- "model.summary()"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "eiH9Y1P8heg4",
- "outputId": "62018b2b-f765-43a9-f487-6e3fd733e6e7"
- },
- "execution_count": 16,
- "outputs": [
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Model: \"sequential\"\n",
- "_________________________________________________________________\n",
- " Layer (type) Output Shape Param # \n",
- "=================================================================\n",
- " dense (Dense) (None, 100) 1400 \n",
- " \n",
- " dense_1 (Dense) (None, 1) 101 \n",
- " \n",
- "=================================================================\n",
- "Total params: 1,501\n",
- "Trainable params: 1,501\n",
- "Non-trainable params: 0\n",
- "_________________________________________________________________\n"
- ]
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "model.compile(optimizer='adam', loss='mse', metrics=['mae'])"
- ],
- "metadata": {
- "id": "lr0HPSnyhedp"
- },
- "execution_count": 17,
- "outputs": []
- },
- {
- "cell_type": "code",
- "source": [
- "history = model.fit(X_train, y_train, batch_size=32, epochs=20, validation_split=0.2)"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "DmNuBukshp9P",
- "outputId": "804ec2d0-ba5c-4f29-d0ce-ea9ce7ca5a6a"
- },
- "execution_count": 18,
- "outputs": [
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "Epoch 1/20\n",
- "11/11 [==============================] - 3s 22ms/step - loss: 557.1730 - mae: 21.9147 - val_loss: 609.2063 - val_mae: 23.0475\n",
- "Epoch 2/20\n",
- "11/11 [==============================] - 0s 7ms/step - loss: 532.9012 - mae: 21.3854 - val_loss: 585.1005 - val_mae: 22.5338\n",
- "Epoch 3/20\n",
- "11/11 [==============================] - 0s 6ms/step - loss: 509.3247 - mae: 20.8655 - val_loss: 560.5905 - val_mae: 22.0077\n",
- "Epoch 4/20\n",
- "11/11 [==============================] - 0s 6ms/step - loss: 486.2475 - mae: 20.3399 - val_loss: 535.8640 - val_mae: 21.4625\n",
- "Epoch 5/20\n",
- "11/11 [==============================] - 0s 7ms/step - loss: 461.9990 - mae: 19.7867 - val_loss: 509.6354 - val_mae: 20.8769\n",
- "Epoch 6/20\n",
- "11/11 [==============================] - 0s 7ms/step - loss: 436.3251 - mae: 19.1894 - val_loss: 481.8866 - val_mae: 20.2395\n",
- "Epoch 7/20\n",
- "11/11 [==============================] - 0s 8ms/step - loss: 410.0367 - mae: 18.5537 - val_loss: 453.0820 - val_mae: 19.5479\n",
- "Epoch 8/20\n",
- "11/11 [==============================] - 0s 6ms/step - loss: 382.7516 - mae: 17.8715 - val_loss: 423.8254 - val_mae: 18.8088\n",
- "Epoch 9/20\n",
- "11/11 [==============================] - 0s 6ms/step - loss: 354.5889 - mae: 17.1212 - val_loss: 392.0852 - val_mae: 17.9759\n",
- "Epoch 10/20\n",
- "11/11 [==============================] - 0s 7ms/step - loss: 325.2735 - mae: 16.2985 - val_loss: 360.8828 - val_mae: 17.1014\n",
- "Epoch 11/20\n",
- "11/11 [==============================] - 0s 7ms/step - loss: 295.4146 - mae: 15.4205 - val_loss: 329.8161 - val_mae: 16.1668\n",
- "Epoch 12/20\n",
- "11/11 [==============================] - 0s 7ms/step - loss: 266.6942 - mae: 14.5040 - val_loss: 299.9690 - val_mae: 15.2050\n",
- "Epoch 13/20\n",
- "11/11 [==============================] - 0s 6ms/step - loss: 238.4964 - mae: 13.5476 - val_loss: 270.8452 - val_mae: 14.2164\n",
- "Epoch 14/20\n",
- "11/11 [==============================] - 0s 6ms/step - loss: 211.5596 - mae: 12.5503 - val_loss: 243.2032 - val_mae: 13.1773\n",
- "Epoch 15/20\n",
- "11/11 [==============================] - 0s 7ms/step - loss: 186.9801 - mae: 11.5573 - val_loss: 217.9993 - val_mae: 12.1424\n",
- "Epoch 16/20\n",
- "11/11 [==============================] - 0s 6ms/step - loss: 165.2683 - mae: 10.6563 - val_loss: 195.9235 - val_mae: 11.2217\n",
- "Epoch 17/20\n",
- "11/11 [==============================] - 0s 7ms/step - loss: 145.9631 - mae: 9.8479 - val_loss: 176.3322 - val_mae: 10.4139\n",
- "Epoch 18/20\n",
- "11/11 [==============================] - 0s 6ms/step - loss: 129.5782 - mae: 9.1388 - val_loss: 159.7129 - val_mae: 9.7597\n",
- "Epoch 19/20\n",
- "11/11 [==============================] - 0s 6ms/step - loss: 115.6311 - mae: 8.5268 - val_loss: 144.8544 - val_mae: 9.1716\n",
- "Epoch 20/20\n",
- "11/11 [==============================] - 0s 7ms/step - loss: 103.5382 - mae: 7.9529 - val_loss: 131.3257 - val_mae: 8.6467\n"
- ]
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "from matplotlib import pyplot as plt"
- ],
- "metadata": {
- "id": "8nhJUJKLiyVW"
- },
- "execution_count": 20,
- "outputs": []
- },
- {
- "cell_type": "code",
- "source": [
- "plt.plot(history.epoch, history.history['loss'])\n",
- "plt.plot(history.epoch, history.history['val_loss'])"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/",
- "height": 283
- },
- "id": "dfYbEqEahs7a",
- "outputId": "ae03afb2-ce90-4d04-8ae1-6d08dd6c4d54"
- },
- "execution_count": 21,
- "outputs": [
- {
- "output_type": "execute_result",
- "data": {
- "text/plain": [
- "[<matplotlib.lines.Line2D at 0x7f54e056a4d0>]"
- ]
- },
- "metadata": {},
- "execution_count": 21
- },
- {
- "output_type": "display_data",
- "data": {
- "image/png": "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\n",
- "text/plain": [
- "<Figure size 432x288 with 1 Axes>"
- ]
- },
- "metadata": {
- "needs_background": "light"
- }
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "plt.plot(history.epoch, history.history['mae'])\n",
- "plt.plot(history.epoch, history.history['val_mae'])"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/",
- "height": 283
- },
- "id": "rr6zjCGFhtu4",
- "outputId": "8deb985f-28fa-4f87-c55c-25c577247769"
- },
- "execution_count": 22,
- "outputs": [
- {
- "output_type": "execute_result",
- "data": {
- "text/plain": [
- "[<matplotlib.lines.Line2D at 0x7f54e0132d50>]"
- ]
- },
- "metadata": {},
- "execution_count": 22
- },
- {
- "output_type": "display_data",
- "data": {
- "image/png": "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\n",
- "text/plain": [
- "<Figure size 432x288 with 1 Axes>"
- ]
- },
- "metadata": {
- "needs_background": "light"
- }
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "model.evaluate(X_test, y_test)"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "-MmP-D5phwcq",
- "outputId": "9c1fbb91-1614-47d8-ccff-a34fbf56e949"
- },
- "execution_count": 23,
- "outputs": [
- {
- "output_type": "stream",
- "name": "stdout",
- "text": [
- "4/4 [==============================] - 0s 4ms/step - loss: 113.3174 - mae: 8.8532\n"
- ]
- },
- {
- "output_type": "execute_result",
- "data": {
- "text/plain": [
- "[113.3174057006836, 8.853187561035156]"
- ]
- },
- "metadata": {},
- "execution_count": 23
- }
- ]
- },
- {
- "cell_type": "code",
- "source": [
- "model.save('models/boston.hdf5')\n",
- "# model.save_weight()"
- ],
- "metadata": {
- "id": "OAySS7O0hy4-"
- },
- "execution_count": 24,
- "outputs": []
- },
- {
- "cell_type": "code",
- "source": [
- "from tensorflow.keras.models import load_model"
- ],
- "metadata": {
- "id": "xQmG2F0Ph08v"
- },
- "execution_count": 25,
- "outputs": []
- },
- {
- "cell_type": "code",
- "source": [
- "old_model = load_model('models/boston.hdf5')"
- ],
- "metadata": {
- "id": "Qp_jE9Fxh3cl"
- },
- "execution_count": 26,
- "outputs": []
- },
- {
- "cell_type": "code",
- "source": [
- "x_new = np.random.rand(X_train.shape[1])\n",
- "x_new = x_new.reshape(1, -1)\n",
- "x_new.shape\n",
- "# Za nove podatke koristi se predict tako da se dobije predvidjena vrednost za y\n",
- "old_model.predict(x_new)"
- ],
- "metadata": {
- "colab": {
- "base_uri": "https://localhost:8080/"
- },
- "id": "yOyueyFmh4CJ",
- "outputId": "d56f0b37-cedc-4456-a527-499b9ff68d7d"
- },
- "execution_count": 27,
- "outputs": [
- {
- "output_type": "execute_result",
- "data": {
- "text/plain": [
- "array([[5.2812877]], dtype=float32)"
- ]
- },
- "metadata": {},
- "execution_count": 27
- }
- ]
- }
- ]
-} \ No newline at end of file
diff --git a/frontend/src/app/_data/Model.ts b/frontend/src/app/_data/Model.ts
index 32247bbd..7a82cc5c 100644
--- a/frontend/src/app/_data/Model.ts
+++ b/frontend/src/app/_data/Model.ts
@@ -28,7 +28,7 @@ export default class Model {
public outputLayerActivationFunction: ActivationFunction = ActivationFunction.Sigmoid,
public username: string = '',
public nullValues: NullValueOptions = NullValueOptions.DeleteRows,
- public nullValuesReplacers = [],
+ public nullValuesReplacers: NullValReplacer[] = [],
public metrics: Metric[] = [], // TODO add to add-model form
public epochs: number = 5 // TODO add to add-model form
) { }
@@ -115,9 +115,15 @@ export enum ReplaceWith {
Median = 'Medijana'
}
+export class NullValReplacer {
+ "column": string;
+ "option": NullValueOptions;
+ "value" : any;
+}
+
export enum Metric {
MSE = 'mse',
MAE = 'mae',
RMSE = 'rmse'
//...
-} \ No newline at end of file
+}
diff --git a/frontend/src/app/_elements/annvisual/annvisual.component.ts b/frontend/src/app/_elements/annvisual/annvisual.component.ts
index ff5b45d6..8588537e 100644
--- a/frontend/src/app/_elements/annvisual/annvisual.component.ts
+++ b/frontend/src/app/_elements/annvisual/annvisual.component.ts
@@ -19,13 +19,13 @@ export class AnnvisualComponent implements OnInit {
let hiddenlayerstring:string='';
let digraphstring:string='digraph {';
- for(let i=0;i<this.model.inputNeurons;i++)
+ for(let i=0;i<this.model.inputColumns.length;i++)
{
inputlayerstring=inputlayerstring+'i'+i+',';
}
inputlayerstring=inputlayerstring.slice(0,-1);
- digraphstring=digraphstring+'->';
+ digraphstring=digraphstring+inputlayerstring+'->';
for(let j=0;j<this.model.hiddenLayers;j++)
{
@@ -33,15 +33,18 @@ export class AnnvisualComponent implements OnInit {
{
hiddenlayerstring=hiddenlayerstring+'h'+j+'_'+i+',';
}
- hiddenlayerstring=hiddenlayerstring.slice(0,1);
+ hiddenlayerstring=hiddenlayerstring.slice(0,-1);
digraphstring=digraphstring+hiddenlayerstring+'->';
hiddenlayerstring='';
}
digraphstring=digraphstring+'o}';
- alert(digraphstring);
+
graphviz('#graph').renderDot(digraphstring);
}
-
+ //'digraph {i0,i1,i2->h1,h2,h3->h21,h22,h23->o}'
}
+
+
+
diff --git a/frontend/src/app/_pages/add-model/add-model.component.html b/frontend/src/app/_pages/add-model/add-model.component.html
index 662d34de..28c84570 100644
--- a/frontend/src/app/_pages/add-model/add-model.component.html
+++ b/frontend/src/app/_pages/add-model/add-model.component.html
@@ -65,7 +65,7 @@
<!-- ULAZNE/IZLAZNE KOLONE -->
<span id="selectInAndOuts"></span>
- <div *ngIf="selectedDataset">
+ <div *ngIf="selectedDataset && (showMyDatasets || (!showMyDatasets && datasetLoaded))"> <!--postignuto da se kod newdataseta ucita tabela pa ulazi/izlazi. ostalo srediti to kod mydatasets(dopuna 2. uslova)-->
<div class="row">
<div class="col d-flex justify-content-center">
<h3>Izaberite ulazne kolone:</h3>
@@ -118,12 +118,15 @@
<div>
<label for="columnReplacers" class="form-label">Unesite zamenu za svaku kolonu:</label>
<div id="columnReplacers">
+ <!--Ulazne kolone - popunjavanje null vrednosti -->
<div *ngFor="let column of selectedDataset.header; let i = index" class="my-3">
<div class="input-group row" *ngIf="getInputById('cb_'+column).checked">
<span class="input-group-text col-2 text-center">
- {{column}}
+ {{column}}&nbsp;<span class="small" style="color:gray;">({{calculateSumOfNullValuesInCol(column)}} null)</span>
</span>
- <input type="text" class="form-control col-2">
+ <input type="text" class="form-control col-1" [id]="'fillText_'+column">
+ <input type="radio" [id]="'fillCol_'+column" class="col-1"
+ [name]="'delOp_'+column"> <!--OVDE SREDI IZGLED-->
<select [id]="'replaceOptions'+i" class="form-control col-2"
*ngIf="isNumber(datasetFile[1][i])">
<option
@@ -147,6 +150,39 @@
checked></label>
</div>
</div>
+ <!--Izlazna kolona - popunjavanje null vrednosti -->
+ <div *ngFor="let column of selectedDataset.header; let i = index" class="my-3"> <!--moze bez for petlje (this.selectedOutputColumnVal je id), al ne moze ova fja array column onda-->
+ <div class="input-group row" *ngIf="getInputById('rb_'+column).checked">
+ <span class="input-group-text col-2 text-center">
+ {{column}}&nbsp;<span class="small" style="color:gray;">({{calculateSumOfNullValuesInCol(column)}} null)</span>
+ </span>
+ <input type="text" class="form-control col-1" [id]="'fillText_'+column">
+ <input type="radio" [id]="'fillCol_'+column" class="col-1"
+ [name]="'delOp_'+column"> <!--OVDE SREDI IZGLED-->
+ <select [id]="'replaceOptions'+i" class="form-control col-2"
+ *ngIf="isNumber(datasetFile[1][i])">
+ <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 col-2"
+ *ngIf="!isNumber(datasetFile[1][i])">
+ <option *ngFor="let option of arrayColumn(datasetFile, i)"
+ [value]="option">
+ {{ option }}
+ </option>
+ </select>
+ <label class="form-control col-2" [for]="'delCol_'+column">Izbriši kolonu
+ <input type="radio" [id]="'delCol_'+column"
+ [name]="'delOp_'+column"></label>
+ <label class="form-control col-2" [for]="'delRows_'+column">Izbriši redove
+ <input type="radio" [id]="'delRows_'+column" [name]="'delOp_'+column"
+ checked></label>
+ </div>
+ </div>
+
</div>
</div>
</div>
@@ -348,4 +384,6 @@
</div>
</div>
-</div> \ No newline at end of file
+</div>
+
+<button (click)="calculateMeanColValue('Age');calculateMedianColValue('Age');">DUGME</button> \ No newline at end of file
diff --git a/frontend/src/app/_pages/add-model/add-model.component.ts b/frontend/src/app/_pages/add-model/add-model.component.ts
index 77a506d5..d47e7426 100644
--- a/frontend/src/app/_pages/add-model/add-model.component.ts
+++ b/frontend/src/app/_pages/add-model/add-model.component.ts
@@ -1,5 +1,5 @@
import { Component, OnInit, ViewChild } from '@angular/core';
-import Model, { ReplaceWith } from 'src/app/_data/Model';
+import Model, { NullValReplacer, ReplaceWith } from 'src/app/_data/Model';
import { ProblemType, Encoding, ActivationFunction, LossFunction, Optimizer, NullValueOptions } from 'src/app/_data/Model';
import { DatasetLoadComponent } from 'src/app/_elements/dataset-load/dataset-load.component';
import { ModelsService } from 'src/app/_services/models.service';
@@ -154,6 +154,8 @@ export class AddModelComponent implements OnInit {
this.tempTestSetDistribution = 90;
this.newModel.username = shared.username;
+ this.newModel.nullValuesReplacers = this.getNullValuesReplacersArray();
+
this.models.addModel(this.newModel).subscribe((response) => {
callback(response);
}, (error) => {
@@ -174,7 +176,7 @@ export class AddModelComponent implements OnInit {
for (let i = 0; i < checkboxes.length; i++) {
let thatCb = <HTMLInputElement>checkboxes[i];
- if (thatCb.checked == true && thatCb.disabled == false)
+ if (thatCb.checked == true) // && thatCb.disabled == false ne treba nam ovo vise
this.newModel.inputColumns.push(thatCb.value);
}
//console.log(this.checkedInputCols);
@@ -231,22 +233,21 @@ export class AddModelComponent implements OnInit {
this.datasets.getDatasetFile(dataset.fileId).subscribe((file: string | undefined) => {
if (file) {
this.datasetFile = this.csv.csvToArray(file, (dataset.delimiter == "razmak") ? " " : (dataset.delimiter == "") ? "," : dataset.delimiter);
- for (let i = this.datasetFile.length - 1; i >= 0; i--) { //moguce da je vise redova na kraju fajla prazno i sl.
+ /*for (let i = this.datasetFile.length - 1; i >= 0; i--) { //moguce da je vise redova na kraju fajla prazno i sl.
if (this.datasetFile[i].length != this.datasetFile[0].length)
this.datasetFile[i].pop();
else
break; //nema potrebe dalje
- }
+ }*/
console.log(this.datasetFile);
+ this.resetCbsAndRbs();
+ //this.refreshThreeNullValueRadioOptions();
}
});
//this.datasetHasHeader = false;
-
- this.resetCbsAndRbs();
}
scrollToNextForm() {
- console.log("USAO U SCROLL");
(<HTMLSelectElement>document.getElementById("selectInAndOuts")).scrollIntoView({
behavior: "smooth",
block: "start",
@@ -292,12 +293,116 @@ export class AddModelComponent implements OnInit {
});
}
+ refreshThreeNullValueRadioOptions() {
+ //console.log((<HTMLInputElement>document.getElementById("delRows")).checked);
+ const input = document.getElementById('delRows');
+ console.log(input); // 👉️ input#subscribe
+
+// ✅ Works
+ //input.checked = true;
+ (<HTMLInputElement>document.getElementById("delRows")).checked = true;
+ (<HTMLInputElement>document.getElementById("delCols")).checked = false;
+ (<HTMLInputElement>document.getElementById("replace")).checked = false;
+ }
+
+ isChecked(someId: string) { //proveri ako je element sa datim ID-em cekiran
+ //console.log(someId);
+ //console.log((<HTMLInputElement>document.getElementById(someId)).checked);
+ return (<HTMLInputElement>document.getElementById(someId)).checked;
+ }
+
isNumber(value: string | number): boolean {
return ((value != null) &&
(value !== '') &&
!isNaN(Number(value.toString())));
}
+ findIndexOfCol(colName: string) : number {
+ if (this.datasetFile)
+ for (let i = 0; i < this.datasetFile[0].length; i++)
+ if (colName === this.datasetFile[0][i])
+ return i;
+ return -1;
+ }
+ calculateSumOfNullValuesInCol(colName: string): number {
+ //console.log(this.datasetFile);
+ if (this.datasetFile) {
+ let colIndex = this.findIndexOfCol(colName);
+ let sumOfNulls = 0;
+ for (let i = 1; i < this.datasetFile.length; i++)
+ if (this.datasetFile[i][colIndex] == '')
+ ++sumOfNulls;
+ //console.log(sumOfNulls);
+ return sumOfNulls;
+ }
+ return -1;
+ }
+ calculateMeanColValue(colName: string): number {
+ if (this.datasetFile) {
+ let colIndex = this.findIndexOfCol(colName);
+ let sum = 0;
+ let n = 0;
+ for (let i = 1; i < this.datasetFile.length; i++)
+ if (this.datasetFile[i][colIndex] != '') {
+ sum += Number(this.datasetFile[i][colIndex]);
+ ++n;
+ }
+ console.log(sum / n);
+ return sum / n;
+ }
+ return 0;
+ }
+ calculateMedianColValue(colName: string): number {
+ if (this.datasetFile) {
+ let array = [];
+ let colIndex = this.findIndexOfCol(colName);
+ for (let i = 1; i < this.datasetFile.length; i++)
+ if (this.datasetFile[i][colIndex] != '')
+ array.push(Number(this.datasetFile[i][colIndex]));
+
+ array.sort();
+ if (array.length % 2 == 0)
+ return array[array.length / 2 - 1] / 2;
+ else
+ return array[(array.length - 1) / 2];
+ }
+ return 0;
+ }
+
+ getNullValuesReplacersArray() : NullValReplacer[] {
+ /*let array: NullValReplacer[] = [];
+
+ //za svaku kolonu
+ if (this.datasetFile) {
+
+ if ((<HTMLInputElement>document.getElementById("delRows")).checked) { //obrisi sve redove
+ this.newModel.nullValues = NullValueOptions.DeleteRows;
+ }
+ else if ((<HTMLInputElement>document.getElementById("delCols")).checked) {
+ this.newModel.nullValues = NullValueOptions.DeleteColumns;
+ }
+ else if ((<HTMLInputElement>document.getElementById("replace")).checked) {
+ this.newModel.nullValues = NullValueOptions.Replace;*/
+
+ //for petlje
+
+ //}
+
+ //proveri ova prva tri rba, ako je 3. cekiran, ide for petlja
+ //if ((<HTMLInputElement>document.getElementById("delCol_" + column)).checked)
+
+ //for (let i = 0; i < this.datasetFile[0].length; i++) { //svi hederi
+ //let column = this.datasetFile[0][i];
+
+ //if ((<HTMLInputElement>document.getElementById("delCol_" + column)).checked) //obrisi celu kolonu
+ //var e = (<HTMLInputElement>document.getElementById("organization")).value;
+ //}
+ //}
+
+
+ return [];
+ }
+
getInputById(id: string): HTMLInputElement {
return document.getElementById(id) as HTMLInputElement;
}
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 f6b78ded..b75decf2 100644
--- a/frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts
+++ b/frontend/src/app/_pages/filter-datasets/filter-datasets.component.ts
@@ -32,9 +32,18 @@ export class FilterDatasetsComponent implements OnInit {
newDataset.isPublic = false;
newDataset.lastUpdated = new Date();
newDataset.username = decodedToken.name;
+ let name=prompt("Unesite naziv dataset-a",newDataset.name);
+ newDataset.name=name as string;
+ if(name!=null && name!="")
this.datasets.addDataset(newDataset).subscribe((response:string)=>{
console.log(response);
+ alert("Uspenso ste dodali dataset sa imenom "+newDataset.name);
+ },(error)=>{
+ alert("Vec imate dataset sa istim imenom molim vas unesite drugo ime");
+
+
});
+
};
}
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 b6926771..e2533d89 100644
--- a/frontend/src/app/_pages/my-models/my-models.component.html
+++ b/frontend/src/app/_pages/my-models/my-models.component.html
@@ -8,6 +8,7 @@
<div class="row">
<div class="col-sm-4" style="margin-bottom: 10px;" *ngFor="let model of myModels">
<app-item-model [model]="model"></app-item-model>
+ <app-annvisual align-items-center [model]="model" style="width: 100%;"></app-annvisual>
<div style="width: 25%; margin: auto;">
<button mat-raised-button color="primary" (click)="deleteThisModel(model)" style="margin-top: 3px; width: 100%;">Obriši</button>
diff --git a/frontend/src/app/_services/auth.service.ts b/frontend/src/app/_services/auth.service.ts
index 449b8802..ccfbe15f 100644
--- a/frontend/src/app/_services/auth.service.ts
+++ b/frontend/src/app/_services/auth.service.ts
@@ -24,10 +24,16 @@ export class AuthService {
return this.http.post(`${API_SETTINGS.apiURL}/auth/register`, { ...user }, { responseType: 'text' });
}
+ getGuestToken(){
+ return this.http.post(`${API_SETTINGS.apiURL}/auth/guestToken`, {}, { responseType: 'text' });
+ }
+
isAuthenticated(): boolean {
if (this.cookie.check('token')) {
var token = this.cookie.get('token');
- return !jwtHelper.isTokenExpired(token);
+ var property=jwtHelper.decodeToken(this.cookie.get('token'));
+ var username=property['name'];
+ return !jwtHelper.isTokenExpired(token) && username!="";
}
return false;
}
@@ -41,12 +47,30 @@ export class AuthService {
if (!exp) {
exp = new Date();
}
- this.refresher = setTimeout(() => {
- console.log('refreshing token!');
- this.http.post(`${API_SETTINGS.apiURL}/auth/renewJwt`, {}, { headers: this.authHeader(), responseType: 'text' }).subscribe((response) => {
- this.authenticate(response);
- });
- }, exp.getTime() - new Date().getTime() - 60000);
+ var property=jwtHelper.decodeToken(this.cookie.get('token'));
+ var username=property['name'];
+ if(username!=""){
+ this.refresher = setTimeout(() => {
+ console.log('refreshing token!');
+ this.http.post(`${API_SETTINGS.apiURL}/auth/renewJwt`, {}, { headers: this.authHeader(), responseType: 'text' }).subscribe((response) => {
+ this.authenticate(response);
+ });
+ }, exp.getTime() - new Date().getTime() - 60000);
+ }
+ else{
+ this.refresher = setTimeout(() => {
+ console.log('refreshing token!');
+ this.getGuestToken().subscribe((response) => {
+ this.authenticate(response);
+ });
+ }, exp.getTime() - new Date().getTime() - 60000);
+ }
+ }
+
+ addGuestToken(){
+ this.getGuestToken().subscribe((token)=>{
+ this.authenticate(token);
+ });
}
authenticate(token: string) {
@@ -74,6 +98,7 @@ export class AuthService {
if (this.refresher)
clearTimeout(this.refresher);
this.shared.loggedIn = false;
+ this.addGuestToken();
}
authHeader() {
diff --git a/frontend/src/app/_services/csv-parse.service.ts b/frontend/src/app/_services/csv-parse.service.ts
index d53f504e..b9b761a0 100644
--- a/frontend/src/app/_services/csv-parse.service.ts
+++ b/frontend/src/app/_services/csv-parse.service.ts
@@ -45,7 +45,8 @@ export class CsvParseService {
strMatchedValue = arrMatches[3];
}
- arrData[arrData.length - 1].push(strMatchedValue);
+ if (strMatchedValue.length > 0)
+ arrData[arrData.length - 1].push(strMatchedValue);
}
return (arrData);
diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts
index f5ae5786..8c6f8452 100644
--- a/frontend/src/app/app.component.ts
+++ b/frontend/src/app/app.component.ts
@@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { filter, map } from 'rxjs';
+import { AuthService } from './_services/auth.service';
@Component({
selector: 'app-root',
@@ -10,7 +11,7 @@ import { filter, map } from 'rxjs';
})
export class AppComponent implements OnInit {
- constructor(private router: Router, private titleService: Title) { }
+ constructor(private router: Router, private titleService: Title,private authService:AuthService) { }
ngOnInit() {
this.router.events
@@ -33,5 +34,9 @@ export class AppComponent implements OnInit {
this.titleService.setTitle(`${title} - Igrannonica`);
}
});
+ if(!this.authService.isAuthenticated())
+ {
+ this.authService.addGuestToken();
+ }
}
}
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index 5d7af9d2..4efab17e 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -38,6 +38,7 @@ import { DatatableComponent } from './_elements/datatable/datatable.component';
import { FilterDatasetsComponent } from './_pages/filter-datasets/filter-datasets.component';
import { ReactiveBackgroundComponent } from './_elements/reactive-background/reactive-background.component';
import { ItemModelComponent } from './_elements/item-model/item-model.component';
+import { AnnvisualComponent } from './_elements/annvisual/annvisual.component';
@NgModule({
declarations: [
@@ -65,7 +66,8 @@ import { ItemModelComponent } from './_elements/item-model/item-model.component'
DatatableComponent,
FilterDatasetsComponent,
ReactiveBackgroundComponent,
- ItemModelComponent
+ ItemModelComponent,
+ AnnvisualComponent
],
imports: [
BrowserModule,