Added front-end ReactApp, with basic CRUD functionality for Bookmark entries
This commit is contained in:
@ -7,12 +7,10 @@ using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using YABA.Common.DTOs;
|
||||
using YABA.Common.DTOs.Bookmarks;
|
||||
using YABA.Common.DTOs.Tags;
|
||||
using YABA.Common.Extensions;
|
||||
using YABA.Common.Interfaces;
|
||||
using YABA.Common.Lookups;
|
||||
using YABA.Data.Context;
|
||||
using YABA.Data.Extensions;
|
||||
using YABA.Models;
|
||||
@ -39,11 +37,11 @@ namespace YABA.Service
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public IEnumerable<BookmarkDTO> GetAll()
|
||||
public IEnumerable<BookmarkDTO> GetAll(bool isHidden = false)
|
||||
{
|
||||
var currentUserId = GetCurrentUserId();
|
||||
|
||||
var userBookmarks = _roContext.Bookmarks.Where(x => x.UserId == currentUserId).ToDictionary(k => k.Id, v => v);
|
||||
var userBookmarks = _roContext.Bookmarks.Where(x => x.UserId == currentUserId && x.IsHidden == isHidden).ToDictionary(k => k.Id, v => v);
|
||||
var bookmarkTagsLookup = _roContext.BookmarkTags
|
||||
.Include(x => x.Tag)
|
||||
.Where(x => userBookmarks.Keys.Contains(x.BookmarkId))
|
||||
@ -86,7 +84,14 @@ namespace YABA.Service
|
||||
|
||||
var newEntity = await _context.Bookmarks.AddAsync(bookmark);
|
||||
|
||||
if (await _context.SaveChangesAsync() > 0) return _mapper.Map<BookmarkDTO>(newEntity.Entity);
|
||||
if (await _context.SaveChangesAsync() > 0)
|
||||
{
|
||||
var bookmarkDTO = _mapper.Map<BookmarkDTO>(newEntity.Entity);
|
||||
|
||||
if(request.Tags != null && request.Tags.Any())
|
||||
bookmarkDTO.Tags.AddRange(await UpdateBookmarkTags(bookmarkDTO.Id, request.Tags));
|
||||
return bookmarkDTO;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -96,8 +101,13 @@ namespace YABA.Service
|
||||
var currentUserId = GetCurrentUserId();
|
||||
|
||||
var bookmark = _context.Bookmarks.FirstOrDefault(x => x.UserId == currentUserId && x.Id == id);
|
||||
var tags = new List<TagSummaryDTO>();
|
||||
|
||||
if(bookmark == null) return null;
|
||||
if (request.Tags != null && request.Tags.Any())
|
||||
tags = (await UpdateBookmarkTags(id, request.Tags)).ToList();
|
||||
|
||||
|
||||
if (bookmark == null) return null;
|
||||
|
||||
bookmark.Title = !string.IsNullOrEmpty(request.Title) ? request.Title : bookmark.Title;
|
||||
bookmark.Description = !string.IsNullOrEmpty(request.Description) ? request.Description : bookmark.Description;
|
||||
@ -106,7 +116,12 @@ namespace YABA.Service
|
||||
bookmark.Url = !string.IsNullOrEmpty(request.Url) ? request.Url : bookmark.Url;
|
||||
UpdateBookmarkWithMetaData(bookmark);
|
||||
|
||||
if (await _context.SaveChangesAsync() > 0) return _mapper.Map<BookmarkDTO>(bookmark);
|
||||
if (await _context.SaveChangesAsync() > 0)
|
||||
{
|
||||
var bookmarkDTO = _mapper.Map<BookmarkDTO>(bookmark);
|
||||
bookmarkDTO.Tags = tags;
|
||||
return bookmarkDTO;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -115,7 +130,8 @@ namespace YABA.Service
|
||||
{
|
||||
var currentUserId = GetCurrentUserId();
|
||||
|
||||
if (!_roContext.Bookmarks.Any(x => x.Id == id && x.UserId == currentUserId)) return null;
|
||||
if (!_roContext.Bookmarks.Any(x => x.Id == id && x.UserId == currentUserId)
|
||||
|| tags == null || !tags.Any()) return null;
|
||||
|
||||
// Add tags that are not yet in the database
|
||||
var savedUserTags = _context.Tags.Where(x => x.UserId == currentUserId).ToList();
|
||||
@ -167,7 +183,7 @@ namespace YABA.Service
|
||||
.ToList();
|
||||
|
||||
var bookmarkDTO = _mapper.Map<BookmarkDTO>(bookmark);
|
||||
bookmarkDTO.Tags = _mapper.Map<IList<TagSummaryDTO>>(bookmarkTags);
|
||||
bookmarkDTO.Tags = _mapper.Map<List<TagSummaryDTO>>(bookmarkTags);
|
||||
|
||||
return bookmarkDTO;
|
||||
}
|
||||
@ -199,12 +215,25 @@ namespace YABA.Service
|
||||
if (!await _roContext.Users.UserExistsAsync(currentUserId)) return null;
|
||||
|
||||
var entriesToDelete = _context.Bookmarks.Where(x => x.UserId == currentUserId && ids.Contains(x.Id)).ToList();
|
||||
var entryIdsToDelete = entriesToDelete.Select(x => x.Id);
|
||||
_context.Bookmarks.RemoveRange(entriesToDelete);
|
||||
|
||||
if (await _context.SaveChangesAsync() <= 0) return null;
|
||||
|
||||
return ids;
|
||||
return entriesToDelete.Select(x => x.Id);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<int>?> HideBookmarks(IEnumerable<int> ids)
|
||||
{
|
||||
var currentUserId = GetCurrentUserId();
|
||||
|
||||
if (!await _roContext.Users.UserExistsAsync(currentUserId)) return null;
|
||||
|
||||
var entriesToHide = _context.Bookmarks.Where(x => x.UserId == currentUserId && ids.Contains(x.Id)).ToList();
|
||||
entriesToHide.ForEach((x) => { x.IsHidden = !x.IsHidden; });
|
||||
|
||||
if(await _context.SaveChangesAsync() <= 0) return null;
|
||||
|
||||
return entriesToHide.Select(x => x.Id);
|
||||
}
|
||||
|
||||
private int GetCurrentUserId()
|
||||
|
||||
@ -10,6 +10,8 @@ namespace YABA.Service.Configuration
|
||||
{
|
||||
services.AddScoped<IUserService, UserService>();
|
||||
services.AddScoped<IBookmarkService, BookmarkService>();
|
||||
services.AddScoped<IMiscService, MiscService>();
|
||||
services.AddScoped<ITagsService, TagsService>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,11 +11,12 @@ namespace YABA.Service.Interfaces
|
||||
Task<BookmarkDTO?> CreateBookmark(CreateBookmarkRequestDTO request);
|
||||
Task<BookmarkDTO?> UpdateBookmark(int id, UpdateBookmarkRequestDTO request);
|
||||
Task<IEnumerable<TagSummaryDTO>?> UpdateBookmarkTags(int id, IEnumerable<string> tags);
|
||||
IEnumerable<BookmarkDTO> GetAll();
|
||||
IEnumerable<BookmarkDTO> GetAll(bool isHidden = false);
|
||||
Task<BookmarkDTO?> Get(int id);
|
||||
IEnumerable<TagSummaryDTO>? GetBookmarkTags(int id);
|
||||
Task<int?> DeleteBookmark(int id);
|
||||
Task<IEnumerable<int>?> DeleteBookmarks(IEnumerable<int> ids);
|
||||
Task<IEnumerable<int>?> HideBookmarks(IEnumerable<int> ids);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
9
YABA.Service/Interfaces/IMiscService.cs
Normal file
9
YABA.Service/Interfaces/IMiscService.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using YABA.Common.DTOs;
|
||||
|
||||
namespace YABA.Service.Interfaces
|
||||
{
|
||||
public interface IMiscService
|
||||
{
|
||||
public WebsiteMetaDataDTO GetWebsiteMetaData(string url);
|
||||
}
|
||||
}
|
||||
10
YABA.Service/Interfaces/ITagsService.cs
Normal file
10
YABA.Service/Interfaces/ITagsService.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using YABA.Common.DTOs.Tags;
|
||||
|
||||
namespace YABA.Service.Interfaces
|
||||
{
|
||||
public interface ITagsService
|
||||
{
|
||||
public IEnumerable<TagSummaryDTO> GetAll();
|
||||
}
|
||||
}
|
||||
53
YABA.Service/MiscService.cs
Normal file
53
YABA.Service/MiscService.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using HtmlAgilityPack;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text.RegularExpressions;
|
||||
using YABA.Common.DTOs;
|
||||
using YABA.Service.Interfaces;
|
||||
|
||||
namespace YABA.Service
|
||||
{
|
||||
public class MiscService : IMiscService
|
||||
{
|
||||
public MiscService() { }
|
||||
|
||||
public WebsiteMetaDataDTO GetWebsiteMetaData(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
var webClient = new WebClient();
|
||||
webClient.Headers.Add("user-agent", "API-Application");
|
||||
var sourceData = webClient.DownloadString(url);
|
||||
var title = Regex.Match(sourceData, @"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value;
|
||||
var description = string.Empty;
|
||||
|
||||
var getHtmlDoc = new HtmlWeb();
|
||||
var document = getHtmlDoc.Load(url);
|
||||
var metaTags = document.DocumentNode.SelectNodes("//meta");
|
||||
if (metaTags != null)
|
||||
{
|
||||
foreach (var sitetag in metaTags)
|
||||
{
|
||||
if (sitetag.Attributes["name"] != null && sitetag.Attributes["content"] != null && sitetag.Attributes["name"].Value == "description")
|
||||
{
|
||||
description = sitetag.Attributes["content"].Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new WebsiteMetaDataDTO
|
||||
{
|
||||
Title = title,
|
||||
Description = description
|
||||
};
|
||||
} catch(Exception)
|
||||
{
|
||||
return new WebsiteMetaDataDTO
|
||||
{
|
||||
Title = url,
|
||||
Description = string.Empty
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
YABA.Service/TagsService.cs
Normal file
47
YABA.Service/TagsService.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using YABA.Common.DTOs.Tags;
|
||||
using YABA.Common.Extensions;
|
||||
using YABA.Data.Context;
|
||||
using YABA.Service.Interfaces;
|
||||
|
||||
namespace YABA.Service
|
||||
{
|
||||
public class TagsService : ITagsService
|
||||
{
|
||||
private readonly YABAReadOnlyContext _roContext;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public TagsService(YABAReadOnlyContext roContext, IHttpContextAccessor httpContextAccessor, IMapper mapper)
|
||||
{
|
||||
_roContext = roContext;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public IEnumerable<TagSummaryDTO> GetAll()
|
||||
{
|
||||
var currentUserId = GetCurrentUserId();
|
||||
|
||||
var activeUserTags = _roContext.BookmarkTags
|
||||
.Include(x => x.Tag)
|
||||
.Where(x => x.Tag.UserId == currentUserId)
|
||||
.ToList()
|
||||
.GroupBy(x => x.Tag.Id)
|
||||
.Select(g => g.First()?.Tag);
|
||||
|
||||
return _mapper.Map<IEnumerable<TagSummaryDTO>>(activeUserTags);
|
||||
|
||||
}
|
||||
|
||||
private int GetCurrentUserId()
|
||||
{
|
||||
int.TryParse(_httpContextAccessor.HttpContext.User.Identity.GetUserId(), out int userId);
|
||||
return userId;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user