aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelena Petrovic <jelenapetrovic.7119@gmail.com>2022-11-12 21:15:45 +0100
committerJelena Petrovic <jelenapetrovic.7119@gmail.com>2022-11-12 21:15:45 +0100
commitaca399bfec3542f34897979bed77f4de8a5531fe (patch)
tree9d5c1afa9e76b03197870d2d1cbd956632d05318
parentc8568d0fdb752c1330e7b35b25a4813f8b44e7f8 (diff)
parent1ce190a8449b9c605af1b2e552c63ba691977460 (diff)
Merge branch 'develop' of http://gitlab.pmf.kg.ac.rs/BrzoDoLokacije2022/odyssey/brzodolokacije into develop
-rw-r--r--Backend/Api/Api/Controllers/LocationController.cs19
-rw-r--r--Backend/Api/Api/Controllers/PostController.cs11
-rw-r--r--Backend/Api/Api/Interfaces/ILocationService.cs2
-rw-r--r--Backend/Api/Api/Interfaces/IPostService.cs2
-rw-r--r--Backend/Api/Api/Models/Location.cs16
-rw-r--r--Backend/Api/Api/Models/Post.cs24
-rw-r--r--Backend/Api/Api/Services/LocationService.cs54
-rw-r--r--Backend/Api/Api/Services/PostService.cs65
-rw-r--r--Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentBrowse.kt35
-rw-r--r--Client/BrzoDoLokacije/app/src/main/res/layout/fragment_browse.xml41
10 files changed, 262 insertions, 7 deletions
diff --git a/Backend/Api/Api/Controllers/LocationController.cs b/Backend/Api/Api/Controllers/LocationController.cs
index bb0b0ab..c9ef9ba 100644
--- a/Backend/Api/Api/Controllers/LocationController.cs
+++ b/Backend/Api/Api/Controllers/LocationController.cs
@@ -50,5 +50,24 @@ namespace Api.Controllers
}
return BadRequest();
}
+
+ [HttpPost("search")]
+ [Authorize(Roles = "User")]
+ public async Task<ActionResult<List<Location>>> searchLocation(int searchtype ,string? query,Coords? coords)
+ {
+ List<Location> ret = new List<Location>();
+ switch (searchtype)
+ {
+ case 1:
+ ret = await _locationService.SearchLocation(query);
+ return Ok(ret);
+ case 2:
+ ret = await _locationService.SearchLocation(coords);
+ return Ok(ret);
+ default:
+ ret = await _locationService.SearchLocation(query);
+ return Ok(ret);
+ }
+ }
}
}
diff --git a/Backend/Api/Api/Controllers/PostController.cs b/Backend/Api/Api/Controllers/PostController.cs
index 3857ce0..3faaa62 100644
--- a/Backend/Api/Api/Controllers/PostController.cs
+++ b/Backend/Api/Api/Controllers/PostController.cs
@@ -116,5 +116,16 @@ namespace Api.Controllers
return Ok();
return BadRequest();
}
+ [HttpGet("locations/{id}/posts")]
+ [Authorize(Roles = "User")]
+ public async Task<ActionResult<List<PostSend>>> searchPosts(string id,int page=0,int sorttype=1,int filterdate=1)
+ {
+ var res = await _postService.SearchPosts(id,page,sorttype,filterdate);
+ if (res != null)
+ {
+ return Ok(res);
+ }
+ return BadRequest();
+ }
}
}
diff --git a/Backend/Api/Api/Interfaces/ILocationService.cs b/Backend/Api/Api/Interfaces/ILocationService.cs
index 16e00a0..b115fdf 100644
--- a/Backend/Api/Api/Interfaces/ILocationService.cs
+++ b/Backend/Api/Api/Interfaces/ILocationService.cs
@@ -7,5 +7,7 @@ namespace Api.Interfaces
Task<Location> add(Location loc);
Task<Location> getById(string id);
Task<List<Location>> getAllLocation();
+ Task<List<Location>> SearchLocation(Coords coords);
+ Task<List<Location>> SearchLocation(string query);
}
} \ No newline at end of file
diff --git a/Backend/Api/Api/Interfaces/IPostService.cs b/Backend/Api/Api/Interfaces/IPostService.cs
index daeee92..0274b26 100644
--- a/Backend/Api/Api/Interfaces/IPostService.cs
+++ b/Backend/Api/Api/Interfaces/IPostService.cs
@@ -15,5 +15,7 @@ namespace Api.Interfaces
Task<List<CommentSend>> CascadeComments(string parentid, Post p);
Task<Boolean> DeleteComments(string postid, string cmntid,string userid);
Task CascadeDeleteComments(string cmntid, Post p);
+ Task<PostSendPage> SearchPosts(string locid, int page = 0, int sorttype = 1, int filterdate = 1);
+ int DateEnumToDays(int filterdate);
}
} \ No newline at end of file
diff --git a/Backend/Api/Api/Models/Location.cs b/Backend/Api/Api/Models/Location.cs
index 7c1a0bf..3402f6c 100644
--- a/Backend/Api/Api/Models/Location.cs
+++ b/Backend/Api/Api/Models/Location.cs
@@ -25,4 +25,20 @@ namespace Api.Models
PLANINA, VISORAVAN, PIRAMIDA, LIVADA, SELO, OSTRVO, POLUOSTRVO, KLISURA, ARHIPELAG,
ADA, DELTA, FJORD, GEJZIR, IZVOR, KOTLINA, MINERALNI_IZVOR, PECINA ,SUMA, VODOPAD,VULKAN
}
+
+ public class Coords
+ {
+ public double latitude { get; set; }
+ public double longitude { get; set; }
+ }
+ public enum SearchType
+ {
+ BY_NAME = 1 ,
+ BY_COORDS =2
+ }
+ public class LocationViews
+ {
+ public Location location { get; set; }
+ public int views { get; set; }
+ }
}
diff --git a/Backend/Api/Api/Models/Post.cs b/Backend/Api/Api/Models/Post.cs
index c832d23..8099d6c 100644
--- a/Backend/Api/Api/Models/Post.cs
+++ b/Backend/Api/Api/Models/Post.cs
@@ -12,6 +12,7 @@ namespace Api.Models
public string ownerId { get; set; }
public string locationId { get; set; }
public string description { get; set; }
+ public DateTime createdAt { get; set; }
public List<string> views { get; set; }
public List<string> reports { get; set; }
public List<Rating> ratings { get; set; }
@@ -33,6 +34,7 @@ namespace Api.Models
public string ownerId { get; set; }
public Location location { get; set; }
public string description { get; set; }
+ public DateTime createdAt { get; set; }
public int views { get; set; }
public double ratings { get; set; }
public List<CommentSend> comments { get; set; }
@@ -74,4 +76,26 @@ namespace Api.Models
public string comment { get; set; }
public string parentId { get; set; }
}
+ public enum SortType
+ {
+ VIEWS_DESC=1,
+ RATING_DESC=2,
+ DATE =3
+ }
+ public enum FilterDate
+ {
+ ALL =1,
+ ONE_YEAR=2 ,
+ THREE_MONTHS=3 ,
+ ONE_MONTH=4 ,
+ ONE_WEEK=5
+ }
+ public class PostSendPage
+ {
+ public int page { get; set; }
+ public int index { get; set; }
+ public int totalpages { get; set; }
+ public int totalposts { get; set; }
+ public List<PostSend> posts { get; set; }
+ }
}
diff --git a/Backend/Api/Api/Services/LocationService.cs b/Backend/Api/Api/Services/LocationService.cs
index e244ed6..c91a1b5 100644
--- a/Backend/Api/Api/Services/LocationService.cs
+++ b/Backend/Api/Api/Services/LocationService.cs
@@ -3,7 +3,9 @@ using Api.Models;
using Geocoding;
using Geocoding.Google;
using Geocoding.MapQuest;
+using MongoDB.Bson;
using MongoDB.Driver;
+using System.Text.RegularExpressions;
using ZstdSharp.Unsafe;
using Location = Api.Models.Location;
@@ -16,10 +18,12 @@ namespace Api.Services
private readonly IHttpContextAccessor _httpContext;
private IConfiguration _configuration;
private MapQuestGeocoder _geocoder;
+ private readonly IMongoCollection<Post> _posts;
public LocationService(IDatabaseConnection settings, IMongoClient mongoClient, IConfiguration configuration)
{
var database = mongoClient.GetDatabase(settings.DatabaseName);
_locations = database.GetCollection<Location>(settings.LocationCollectionName);
+ _posts = database.GetCollection<Post>(settings.PostCollectionName);
_configuration = configuration;
var _mapQuestApiKey = _configuration.GetSection("AppSettings:MapQuestApiKey").Value;
_geocoder = new MapQuestGeocoder(_mapQuestApiKey);
@@ -43,5 +47,55 @@ namespace Api.Services
{
return await _locations.Find(_=>true).ToListAsync();
}
+
+ public async Task<List<Location>> SearchLocation(Coords coords) // returns all locations within coord radius 1/5th of a degree of lat and long
+ {
+ if (coords == null)
+ return null;
+ var lista = await _locations.Find(_ => true).ToListAsync();
+ var tosend = new List<Location>();
+ if (lista != null)
+ {
+ foreach (var elem in lista)
+ {
+ if (Math.Abs(elem.latitude - coords.latitude) < 0.2 && Math.Abs(elem.longitude - coords.longitude) < 0.2)
+ tosend.Add(elem);
+ }
+ }
+ return tosend;
+ }
+ public async Task<List<Location>> SearchLocation(string query) //returns 10 (n) most relevant locations when searching by name
+ {
+ if (query == null) query = "";
+ else query = query.ToLower();
+ var lista = await _locations.Find(x => x.name.ToLower().Contains(query)).ToListAsync();
+ var tosend = new List<Location>();
+ if (lista != null)
+ {
+ var locviews = new List<LocationViews>();
+ foreach (var elem in lista)
+ {
+ var totalviews = 0;
+ var posts = await _posts.Find(x => x.locationId == elem._id).ToListAsync();
+ if(posts != null)
+ {
+ foreach(var post in posts)
+ {
+ totalviews += post.views.Count();
+ }
+ }
+ var novi = new LocationViews();
+ novi.location = elem;
+ novi.views = totalviews;
+ locviews.Add(novi);
+ }
+ var top10 = locviews.OrderByDescending(x => x.views).Take(10).ToList();
+ foreach(var view in top10)
+ {
+ tosend.Add(view.location);
+ }
+ }
+ return tosend;
+ }
}
}
diff --git a/Backend/Api/Api/Services/PostService.cs b/Backend/Api/Api/Services/PostService.cs
index 78167bd..a0b2941 100644
--- a/Backend/Api/Api/Services/PostService.cs
+++ b/Backend/Api/Api/Services/PostService.cs
@@ -38,7 +38,7 @@ namespace Api.Services
p.ratings = new List<Rating>();
p.comments = new List<Comment>();
p.images = new List<Models.File>();
-
+ p.createdAt = DateTime.Now.ToUniversalTime();
var folderPath = Path.Combine(Directory.GetCurrentDirectory(), "Files", p.ownerId);
if (!Directory.Exists(folderPath))
{
@@ -75,13 +75,13 @@ namespace Api.Services
public async Task<PostSend> postToPostSend(Post post)
{
PostSend p = new PostSend();
- //Convert post to post send (TODO)
p._id = post._id;
p.ownerId = post.ownerId;
p.description = post.description;
p.location = await _locationService.getById(post.locationId);
p.images = post.images;
p.views = post.views.Count();
+ p.createdAt = post.createdAt;
if (post.ratings.Count() > 0)
{
List<int> ratings = new List<int>();
@@ -275,5 +275,66 @@ namespace Api.Services
}
}
}
+ public async Task<PostSendPage> SearchPosts(string locid,int page = 0,int sorttype = 1 ,int filterdate = 1) // for now sorting by number of ratings , not avg rating
+ {
+ var days = DateEnumToDays(filterdate);
+ var tosend = new PostSendPage();
+ var pslista = new List<PostSend>();
+ var lista = new List<Post>();
+ var ls = new List<PostSend>();
+ var xd = new List<PostSend>();
+ lista = await _posts.Find(x => x.locationId == locid).ToListAsync();
+ if (lista != null)
+ {
+ foreach (var elem in lista)
+ {
+ if ((DateTime.Now - elem.createdAt).TotalDays < days)
+ ls.Add(await postToPostSend(elem));
+ }
+
+ }
+ switch (sorttype)
+ {
+ case 1:
+ xd = ls.OrderByDescending(x => x.views).ToList();
+ break;
+ case 2:
+ xd = ls.OrderByDescending(x => x.ratings).ToList();
+ break;
+ case 3:
+ xd = ls.OrderByDescending(x => x.createdAt).ToList();
+ break;
+ default:
+
+ break;
+ }
+ if(xd != null)
+ {
+ tosend.page = page;
+ tosend.index = page * 20;
+ tosend.totalposts = xd.Count();
+ double pgs = xd.Count / 20;
+ tosend.totalpages = (int)Math.Ceiling(pgs);
+ var selected = ls.Skip(20 * page).Take(20);
+ foreach(var post in selected)
+ {
+ pslista.Add(post);
+ }
+ tosend.posts = pslista;
+ }
+ return tosend;
+ }
+ public int DateEnumToDays(int filterdate)
+ {
+ switch(filterdate)
+ {
+ case 1: return 365 * 10;
+ case 2: return 365;
+ case 3: return 90;
+ case 4: return 30;
+ case 5: return 7;
+ default: return 365 * 10;
+ }
+ }
}
}
diff --git a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentBrowse.kt b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentBrowse.kt
index ec6673c..08d0fdd 100644
--- a/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentBrowse.kt
+++ b/Client/BrzoDoLokacije/app/src/main/java/com/example/brzodolokacije/Fragments/FragmentBrowse.kt
@@ -13,11 +13,15 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.Button
+import android.widget.EditText
+import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.example.brzodolokacije.R
import com.example.brzodolokacije.Services.GeocoderHelper
+import com.google.android.material.floatingactionbutton.FloatingActionButton
import org.osmdroid.config.Configuration
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
import org.osmdroid.util.GeoPoint
@@ -37,6 +41,8 @@ class FragmentBrowse : Fragment(R.layout.fragment_browse) {
var mRotationGestureOverlay:RotationGestureOverlay?=null
var mScaleBarOverlay: ScaleBarOverlay?=null
var mCompassOverlay:CompassOverlay?=null
+ private lateinit var searchButton:FloatingActionButton
+ private lateinit var searchBar: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -53,6 +59,14 @@ class FragmentBrowse : Fragment(R.layout.fragment_browse) {
map=v.findViewById(R.id.FragmentBrowseMapView) as MapView
map!!.setTileSource(TileSourceFactory.MAPNIK);
setUpMap()
+ searchButton=v.findViewById<View>(R.id.FragmentBrowseSearchButton) as FloatingActionButton
+ searchBar=v.findViewById<View>(R.id.FragmentBrowseSearchBar) as EditText
+
+ searchButton.setOnClickListener{
+ searchMap()
+ }
+
+
return v
}
@@ -77,8 +91,7 @@ class FragmentBrowse : Fragment(R.layout.fragment_browse) {
mLocationOverlay = MyLocationNewOverlay(GpsMyLocationProvider(context), map)
mLocationOverlay!!.enableMyLocation()
map!!.getOverlays().add(this.mLocationOverlay)
- var res= GeocoderHelper.getInstance()
- Log.d("Main",res!!.getFromLocationName("Paris",1)[0].countryName)
+
//start point
val startPoint = GeoPoint(44.0107,20.9181)//dodati nasu lokaciju TODO
mapController.setCenter(startPoint)
@@ -125,6 +138,24 @@ class FragmentBrowse : Fragment(R.layout.fragment_browse) {
//your codes here
}
}
+ fun searchMap(){
+ var geocoder= GeocoderHelper.getInstance()
+ //Log.d("Main",geocoder!!.getFromLocationName("Paris",1)[0].countryName)
+ var locString=searchBar.text.toString().trim()
+ if(locString==null || locString=="")
+ Toast.makeText(requireContext(),"Unesite naziv lokacije",Toast.LENGTH_SHORT)
+ else{
+ var result=geocoder!!.getFromLocationName(locString,1)[0]
+ if(result==null)
+ Toast.makeText(requireContext(),"Nepostojeca lokacija",Toast.LENGTH_SHORT)
+ else{
+ //move to spot
+ map!!.controller.animateTo(GeoPoint(result.latitude,result.longitude))
+
+
+ }
+ }
+ }
} \ No newline at end of file
diff --git a/Client/BrzoDoLokacije/app/src/main/res/layout/fragment_browse.xml b/Client/BrzoDoLokacije/app/src/main/res/layout/fragment_browse.xml
index a811522..cdccaa6 100644
--- a/Client/BrzoDoLokacije/app/src/main/res/layout/fragment_browse.xml
+++ b/Client/BrzoDoLokacije/app/src/main/res/layout/fragment_browse.xml
@@ -1,14 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragments.FragmentBrowse">
+
+
+
<org.osmdroid.views.MapView
android:id="@+id/FragmentBrowseMapView"
android:layout_width="fill_parent"
- android:layout_height="fill_parent"/>
+ android:layout_height="fill_parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="@+id/FragmentBrowseSearchBar" />
+
+ <com.google.android.material.textfield.TextInputEditText
+ android:id="@+id/FragmentBrowseSearchBar"
+ android:layout_width="250dp"
+ android:layout_height="55dp"
+ android:layout_marginTop="40dp"
+ android:background="@drawable/rounded_white_button_login"
+ android:ems="10"
+ android:hint=" Pretraga"
+ android:inputType="textPersonName"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
+ android:id="@+id/FragmentBrowseSearchButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:backgroundTint="#FFFFFF"
+ android:clickable="true"
+ android:focusable="true"
+ android:tint="#FFFFFF"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toEndOf="@+id/FragmentBrowseSearchBar"
+ app:layout_constraintTop_toTopOf="@+id/FragmentBrowseSearchBar"
+ app:rippleColor="#FFFFFF"
+ app:srcCompat="@android:drawable/ic_search_category_default" />
-</FrameLayout> \ No newline at end of file
+</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file