diff options
author | Ognjen Cirkovic <ciraboxkg@gmail.com> | 2022-12-06 17:25:53 +0000 |
---|---|---|
committer | Ognjen Cirkovic <ciraboxkg@gmail.com> | 2022-12-06 17:25:53 +0000 |
commit | 5a205c35d936728f76451109751e1fb5a9a75bd1 (patch) | |
tree | 2a1f7296e2186a895d730579cabc7130713f16cf /Backend | |
parent | b76cefc486097d776e3ff374b27ce3bfb0786b56 (diff) | |
parent | f7e16147ecb993af365c6d132f2782b73255fe2c (diff) |
Merge branch 'develop' into 'master'
Merge develop->master
See merge request BrzoDoLokacije2022/odyssey/brzodolokacije!10
Diffstat (limited to 'Backend')
-rw-r--r-- | Backend/Api/Api/Controllers/LocationController.cs | 22 | ||||
-rw-r--r-- | Backend/Api/Api/Controllers/PostController.cs | 13 | ||||
-rw-r--r-- | Backend/Api/Api/Controllers/UserController.cs | 41 | ||||
-rw-r--r-- | Backend/Api/Api/Interfaces/IPostService.cs | 4 | ||||
-rw-r--r-- | Backend/Api/Api/Interfaces/IUserService.cs | 4 | ||||
-rw-r--r-- | Backend/Api/Api/Models/Post.cs | 9 | ||||
-rw-r--r-- | Backend/Api/Api/Models/User.cs | 15 | ||||
-rw-r--r-- | Backend/Api/Api/Services/LocationService.cs | 2 | ||||
-rw-r--r-- | Backend/Api/Api/Services/PostService.cs | 163 | ||||
-rw-r--r-- | Backend/Api/Api/Services/UserService.cs | 69 |
10 files changed, 338 insertions, 4 deletions
diff --git a/Backend/Api/Api/Controllers/LocationController.cs b/Backend/Api/Api/Controllers/LocationController.cs index ba9c9a8..ac093bb 100644 --- a/Backend/Api/Api/Controllers/LocationController.cs +++ b/Backend/Api/Api/Controllers/LocationController.cs @@ -12,9 +12,11 @@ namespace Api.Controllers public class LocationController : ControllerBase { private readonly ILocationService _locationService; - public LocationController(ILocationService locationService) + private readonly IPostService _postService; + public LocationController(ILocationService locationService, IPostService postService) { _locationService = locationService; + _postService = postService; } [HttpPost("add")] @@ -74,5 +76,23 @@ namespace Api.Controllers return Ok(ret); } } + + [HttpGet("searchradius")] + [Authorize(Roles = "User")] + public async Task<ActionResult<List<Location>>> bestPostsForLocationInRadius(double latitude, double longitude, double radius) + { + Coords coords = new Coords(); + if (latitude != null && longitude != null) + { + coords.latitude = (double)latitude; + coords.longitude = (double)longitude; + } + List<PostSend> ret = new List<PostSend>(); + ret = await _postService.BestPostForAllLocationsInRadius(coords, radius); + if (ret != null && ret.Count > 0) + return Ok(ret); + return BadRequest(); + + } } } diff --git a/Backend/Api/Api/Controllers/PostController.cs b/Backend/Api/Api/Controllers/PostController.cs index 03c3f81..61a4f48 100644 --- a/Backend/Api/Api/Controllers/PostController.cs +++ b/Backend/Api/Api/Controllers/PostController.cs @@ -186,5 +186,18 @@ namespace Api.Controllers var userid = await _userService.UserIdFromJwt(); return Ok(await _postService.Recommended(userid)); } + [HttpGet("favourite/{id}")] + [Authorize(Roles = "User")] + public async Task<ActionResult<bool>> addRemoveFavourite(string id) + { + return Ok(await _postService.addRemoveFavourite(id)); + } + + [HttpGet("trending")] + [Authorize(Roles = "User")] + public async Task<ActionResult<List<Trending>>> Trending() + { + return Ok(await _postService.TrendingTags()); + } } } diff --git a/Backend/Api/Api/Controllers/UserController.cs b/Backend/Api/Api/Controllers/UserController.cs index 4d7905a..73d32ea 100644 --- a/Backend/Api/Api/Controllers/UserController.cs +++ b/Backend/Api/Api/Controllers/UserController.cs @@ -123,5 +123,46 @@ namespace Api.Controllers { return Ok(await _userService.GetMyFollowers()); } + + [HttpGet("profile/stats")] + [Authorize(Roles = "User")] + public async Task<ActionResult<UserStats>> SelfStats() + { + var id = await _userService.UserIdFromJwt(); + var tosend = await _postService.UserStats(id); + if (tosend != null) + return Ok(tosend); + return BadRequest(); + } + [HttpGet("{username}/profile/stats")] + [Authorize(Roles = "User")] + public async Task<ActionResult<UserStats>> GetStats(string username) + { + var rez = await _userService.GetUserData(username); + if (rez == null) + return BadRequest(); + var tosend = await _postService.UserStats(rez._id); + if (tosend != null) + return Ok(tosend); + return BadRequest(); + } + + [HttpGet("{newUsername}/changeMyUsername")] + [Authorize(Roles = "User")] + public async Task<ActionResult<int>> ChangeMyProfileUsername(string newUsername) + { + return await _userService.ChangeMyProfileUsername(newUsername); + } + + + [HttpGet("{newName}/changeMyName")] + [Authorize(Roles = "User")] + public async Task<ActionResult<bool>> ChangeMyProfileName(string newName) + { + return Ok(await _userService.ChangeMyProfileName(newName)); + } + + + } } diff --git a/Backend/Api/Api/Interfaces/IPostService.cs b/Backend/Api/Api/Interfaces/IPostService.cs index 96786bd..c854601 100644 --- a/Backend/Api/Api/Interfaces/IPostService.cs +++ b/Backend/Api/Api/Interfaces/IPostService.cs @@ -27,5 +27,9 @@ namespace Api.Interfaces Task<List<PostSend>> Get10Newest(); Task<List<PostSend>> Recommended(string userid); + Task<Boolean> addRemoveFavourite(string postId); + Task<List<Trending>> TrendingTags(); + Task<List<PostSend>> BestPostForAllLocationsInRadius(Coords coords, double radius); + Task<UserStats> UserStats(string userid); } }
\ No newline at end of file diff --git a/Backend/Api/Api/Interfaces/IUserService.cs b/Backend/Api/Api/Interfaces/IUserService.cs index 95dd46d..f4954e0 100644 --- a/Backend/Api/Api/Interfaces/IUserService.cs +++ b/Backend/Api/Api/Interfaces/IUserService.cs @@ -37,5 +37,9 @@ namespace Api.Interfaces Task<List<UserSend>> GetMyFollowers(); + Task<int> ChangeMyProfileUsername(String newUsername); + Task<bool> ChangeMyProfileName(String newUsername); + + } } diff --git a/Backend/Api/Api/Models/Post.cs b/Backend/Api/Api/Models/Post.cs index dd007ec..9c0c429 100644 --- a/Backend/Api/Api/Models/Post.cs +++ b/Backend/Api/Api/Models/Post.cs @@ -19,6 +19,7 @@ namespace Api.Models public List<Comment> comments { get; set; } public List<File> images { get; set; } public List<string>? tags { get; set; } + public List<string>? favourites { get; set; } } public class PostReceive @@ -43,6 +44,7 @@ namespace Api.Models public List<File> images { get; set; } public List<string>? tags { get; set; } public DateTime? lastViewed { get; set; } + public List<string>? favourites { get; set; } } public class Rating { @@ -113,5 +115,12 @@ namespace Api.Models { public int counter { get; set; } public string tag { get; set; } + public int? views { get; set; } + } + + public class Trending + { + public TagR tagr { get; set; } + public PostSendPage page { get; set; } } } diff --git a/Backend/Api/Api/Models/User.cs b/Backend/Api/Api/Models/User.cs index 6c777e7..cf16dbe 100644 --- a/Backend/Api/Api/Models/User.cs +++ b/Backend/Api/Api/Models/User.cs @@ -72,4 +72,19 @@ namespace Api.Models } + + public class UserStats + { + public int totalViews { get; set; } + public int numberOfPosts { get; set; } + public int numberOfRatingsOnPosts { get; set; } + public double averagePostRatingOnPosts {get; set; } + public List<MonthlyViews> monthlyViews { get; set; } + } + + public class MonthlyViews + { + public int month { get; set; } + public int views { get; set; } + } } diff --git a/Backend/Api/Api/Services/LocationService.cs b/Backend/Api/Api/Services/LocationService.cs index afb3b5b..55a52e7 100644 --- a/Backend/Api/Api/Services/LocationService.cs +++ b/Backend/Api/Api/Services/LocationService.cs @@ -99,5 +99,7 @@ namespace Api.Services } return tosend; } + + } } diff --git a/Backend/Api/Api/Services/PostService.cs b/Backend/Api/Api/Services/PostService.cs index 855b231..6d28206 100644 --- a/Backend/Api/Api/Services/PostService.cs +++ b/Backend/Api/Api/Services/PostService.cs @@ -15,6 +15,7 @@ namespace Api.Services private readonly IFileService _fileService; private readonly ILocationService _locationService; private readonly IMongoCollection<User> _users; + private readonly IMongoCollection<Location> _locations; public PostService(IDatabaseConnection settings, IMongoClient mongoClient, IHttpContextAccessor httpContext, IFileService fileService,ILocationService locationService) { var database = mongoClient.GetDatabase(settings.DatabaseName); @@ -23,6 +24,7 @@ namespace Api.Services _httpContext = httpContext; _fileService = fileService; _locationService = locationService; + _locations = database.GetCollection<Location>(settings.LocationCollectionName); } public async Task<PostSend> addPost(PostReceive post) @@ -89,6 +91,7 @@ namespace Api.Services p.createdAt = post.createdAt; p.tags = post.tags; p.ratingscount = post.ratings.Count(); + p.favourites = post.favourites; if (post.ratings.Count() > 0) { List<int> ratings = new List<int>(); @@ -346,7 +349,27 @@ namespace Api.Services 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(ObjectId.TryParse(locid, out _)) + lista = await _posts.Find(x => x.locationId == locid).ToListAsync(); + else + { + lista = await _posts.Find(x => x.tags != null && x.tags.Any(y => y.ToLower().Contains(locid.ToLower()))).ToListAsync(); + if (lista.Count==0) + { + var locs = await _locations.Find(x => x.city.ToLower().Contains(locid.ToLower()) || x.name.ToLower().Contains(locid.ToLower())).ToListAsync(); + foreach(var loc in locs) + { + var posts =await _posts.Find(x => x.locationId == loc._id).ToListAsync(); + if(posts != null) + { + foreach(var p in posts) + { + lista.Add(p); + } + } + } + } + } if (lista != null) { foreach (var elem in lista) @@ -471,7 +494,7 @@ namespace Api.Services public async Task<List<PostSend>> Recommended(string userid) // momgodb bloat bleh { List<PostSend> posts = await UserHistory(userid); - //TODO-LIMIT RECOMMENDED FOR POSTS FROM THIS MONTH ONLY + //TODO-LIMIT RECOMMENDED FOR POSTS FROM THIS MONTH List<TagR> tags = new List<TagR>(); foreach (var post in posts) { @@ -530,5 +553,141 @@ namespace Api.Services taggedposts = fiveoftop5tags.Distinct().OrderByDescending(x => x.createdAt).ToList(); return taggedposts; } + public async Task<Boolean> addRemoveFavourite(string postId) + { + string userId = _httpContext.HttpContext.User.FindFirstValue("id"); + var result = false; + Post post = await _posts.Find(x => x._id == postId).FirstOrDefaultAsync(); + if (userId == null || post==null) + return result; + if (post.favourites == null) + post.favourites = new List<string>(); + if (post.favourites.Contains(userId)) + { + post.favourites.Remove(userId); + result = false; + } + else + { + post.favourites.Add(userId); + result = true; + + } + await _posts.ReplaceOneAsync(x => x._id == postId, post); + return result; + + } + + public async Task<List<Trending>> TrendingTags() + { + var all = await _posts.Find(_ => true).ToListAsync(); + var posts = new List<PostSend>(); + foreach (var elem in all) + { + if ((DateTime.Now - elem.createdAt).TotalDays < 7) + posts.Add(await postToPostSend(elem)); + } + List<TagR> tags = new List<TagR>(); + foreach (var post in posts) + { + if (post.tags != null) + { + foreach (var tagitem in post.tags) + { + if (!tags.Any(x => x.tag == tagitem)) + { + var newtag = new TagR(); + newtag.tag = tagitem; + newtag.counter = 1; + newtag.views = post.views; + tags.Add(newtag); + } + else + { + var replace = tags.Find(x => x.tag == tagitem); + tags.Remove(replace); + replace.counter += 1; + replace.views += post.views; + tags.Add(replace); + } + } + } + } + var top10tags = tags.OrderByDescending(x => x.views).Take(10).ToList(); + + var tosend = new List<Trending>(); + foreach(var trending in top10tags) + { + var novi = new Trending(); + novi.tagr = trending; + novi.page = await SearchPosts(trending.tag, 0, 1, 5); + tosend.Add(novi); + } + + return tosend; + } + + public async Task<List<PostSend>> BestPostForAllLocationsInRadius(Coords coords, double radius) + { + if (coords == null) + return null; + var lista = await _locations.Find(_ => true).ToListAsync(); + var inradius = new List<Location>(); + var tosend = new List<PostSend>(); + if (lista != null) + { + foreach (var elem in lista) + { + if (Math.Abs(elem.latitude - coords.latitude) < radius && Math.Abs(elem.longitude - coords.longitude) < radius) + inradius.Add(elem); + } + foreach (var elem in inradius) + { + var locposts = await SearchPosts(elem._id, 0, 1, 1); + var best = locposts.posts.Take(1).FirstOrDefault(); + if(best != null) + tosend.Add(best); + } + } + return tosend; + } + + public async Task<UserStats> UserStats(string userid) + { + var posts = await GetUsersPosts(userid); + var stats = new UserStats(); + double ratingsum = 0; + stats.averagePostRatingOnPosts = 0; + stats.numberOfRatingsOnPosts = 0; + stats.numberOfPosts = 0; + stats.totalViews = 0; + stats.monthlyViews = new List<MonthlyViews>(); + + + if(posts != null) + { + for(int i = 1; i <= 12; i++) + { + var novi = new MonthlyViews(); + novi.month = i; + novi.views = 0; + stats.monthlyViews.Add(novi); + } + + foreach (var post in posts) + { + var month = post.createdAt.Month; + stats.monthlyViews.FirstOrDefault(x => x.month == month).views += post.views; + stats.totalViews += post.views; + stats.numberOfRatingsOnPosts += post.ratingscount; + stats.numberOfPosts++; + ratingsum += post.ratings * post.ratingscount; + } + if(stats.numberOfRatingsOnPosts > 0) //don't forget to check div by 0 jesus + stats.averagePostRatingOnPosts = ratingsum / stats.numberOfRatingsOnPosts; + } + return stats; + } } + } diff --git a/Backend/Api/Api/Services/UserService.cs b/Backend/Api/Api/Services/UserService.cs index ec67729..781afa8 100644 --- a/Backend/Api/Api/Services/UserService.cs +++ b/Backend/Api/Api/Services/UserService.cs @@ -360,6 +360,10 @@ namespace Api.Services tosend._id= user._id; tosend.creationDate = user.creationDate; tosend.email=""; + tosend.followersCount = user.followersCount; + tosend.followingCount = user.followingCount; + tosend.followers = user.followers; + tosend.following = user.following; var userposts = await _posts.Find(x => x.ownerId == user._id).ToListAsync(); tosend.postcount = userposts.Count(); return tosend; @@ -376,6 +380,10 @@ namespace Api.Services tosend._id = user._id; tosend.creationDate = user.creationDate; tosend.email = user.email; + tosend.followersCount = user.followersCount; + tosend.followingCount = user.followingCount; + tosend.followers = user.followers; + tosend.following = user.following; var userposts = await _posts.Find(x => x.ownerId == user._id).ToListAsync(); tosend.postcount = userposts.Count(); return tosend; @@ -466,6 +474,9 @@ namespace Api.Services follower.email = utemp.username; follower.following = utemp.following; follower.followers = utemp.followers; + follower.followersCount = utemp.followersCount; + follower.followingCount = utemp.followingCount; + follower._id = utemp._id; followers.Add((UserSend)follower); @@ -502,6 +513,8 @@ namespace Api.Services follower.following = utemp.following; follower.followers = utemp.followers; follower._id = utemp._id; + follower.followersCount = utemp.followersCount; + follower.followingCount = utemp.followingCount; following.Add((UserSend)follower); } @@ -543,6 +556,8 @@ namespace Api.Services following.following = utemp.following; following.followers = utemp.followers; following._id = utemp._id; + following.followersCount = utemp.followersCount; + following.followingCount = utemp.followingCount; myFollowings.Add((UserSend)following); } @@ -654,8 +669,9 @@ namespace Api.Services follower.email = utemp.username; follower.following = utemp.following; follower.followers = utemp.followers; + follower.followersCount = utemp.followersCount; + follower.followingCount = utemp.followingCount; follower._id = utemp._id; - myfollowers.Add((UserSend)follower); } return myfollowers; @@ -663,6 +679,57 @@ namespace Api.Services return null; } + + public async Task<int> ChangeMyProfileUsername(string newUsername) + { + string myId = null; + + if (_httpContext.HttpContext.User.FindFirstValue("id") != null) + { + myId = _httpContext.HttpContext.User.FindFirstValue("id").ToString(); + } + User u = await _users.Find(user => user._id == myId).FirstOrDefaultAsync(); + if (u != null) + { + + //da li username vec postoji? + if (await _users.Find(x => x.username == newUsername).FirstOrDefaultAsync() != null) + { + //vec postoji korisnik sa navedenim korisnickim imenom + return -1; + } + else + { + u.username = newUsername; + await _users.ReplaceOneAsync(x => x._id == u._id, u); + return 1; + } + + } + return -2; + + } + + public async Task<bool> ChangeMyProfileName(string newName) + { + string myId = null; + if (_httpContext.HttpContext.User.FindFirstValue("id") != null) + { + myId = _httpContext.HttpContext.User.FindFirstValue("id").ToString(); + } + User u = await _users.Find(user => user._id == myId).FirstOrDefaultAsync(); + if (u != null) + { + + u.name = newName; + await _users.ReplaceOneAsync(x => x._id == u._id, u); + return true; + + } + return false; + } + + } } |