Skip to content

Commit

Permalink
Account page (#18)
Browse files Browse the repository at this point in the history
* initial account page

* admin page components

* created pwa support, added account page, refactored api calls methods

* added loading state in card components. changed main page content width

* added pwa support files

* fix response timeout

* some improvements. account page navigation

* created account page with profile and articles subpages

* serverside updates for account page

* account page improvements
  • Loading branch information
KrawMire committed Sep 30, 2023
1 parent 92fa3fb commit 4cf2f1d
Show file tree
Hide file tree
Showing 141 changed files with 3,122 additions and 1,398 deletions.
41 changes: 41 additions & 0 deletions ScienceArchive.DB/functions/articles/get_articles_by_author_id.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
CREATE OR REPLACE FUNCTION "func_get_articles_by_author_id" (
"p_author_id" UUID
)
RETURNS TABLE (
"id" UUID,
"categoryId" UUID,
"title" VARCHAR(255),
"description" TEXT,
"creationDate" TIMESTAMP,
"authorsIds" UUID[],
"documents" JSONB
)
LANGUAGE plpgsql
AS $$
BEGIN
RETURN QUERY
SELECT
a."id",
ac."subcategory_id",
a."title",
a."description",
acr."created_timestamp" AS "creationDate",
(
SELECT
array_agg(ac."author_id")
FROM "articles_authors" as ac
WHERE ac."article_id" = a."id"
) AS "authorsIds",
(
SELECT
jsonb_agg(
json_build_object('document_path', ad."document_path")
)
FROM "articles_documents" AS ad
WHERE ad."article_id" = a."id"
) AS "documents"
FROM "articles" AS a
INNER JOIN "articles_categories" AS ac ON ac."article_id" = a."id"
INNER JOIN "articles_creation" AS acr ON acr."article_id" = a."id"
INNER JOIN "articles_authors" AS aa ON aa."article_id" = a."id" and aa."author_id" = "p_author_id";
END;$$
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ScienceArchive.Application.Dtos.Article.Request;

/// <summary>
/// DTO contract to get articles by author ID
/// </summary>
/// <param name="AuthorId">Author ID</param>
public record GetArticlesByAuthorIdRequestDto(string AuthorId);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ScienceArchive.Application.Dtos.Article.Response;

/// <summary>
/// Response DTO of getting articles by author ID
/// </summary>
/// <param name="Articles">Result set of articles with specified author ID</param>
public record GetArticlesByAuthorIdResponseDto(List<ArticleDto> Articles);
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using ScienceArchive.Core.Domain.Aggregates.Article;
using ScienceArchive.Core.Domain.Aggregates.Article.ValueObjects;
using ScienceArchive.Core.Domain.Aggregates.Category.ValueObjects;
using ScienceArchive.Core.Domain.Aggregates.User.ValueObjects;
using ScienceArchive.Core.Services;
using ScienceArchive.Core.Services.ArticleContracts;

Expand All @@ -32,6 +33,16 @@ public async Task<GetAllArticlesResponseDto> GetAllArticles(GetAllArticlesReques
return new(articlesDtos);
}

/// <inheritdoc/>
public async Task<GetArticlesByAuthorIdResponseDto> GetArticlesByAuthorId(GetArticlesByAuthorIdRequestDto dto)
{
var contract = new GetArticlesByAuthorIdContract(UserId.CreateFromString(dto.AuthorId));
var articles = await _articleService.GetByAuthorId(contract);

var articlesDtos = articles.Select(_articleMapper.MapToDto).ToList();
return new GetArticlesByAuthorIdResponseDto(articlesDtos);
}

/// <inheritdoc/>
public async Task<GetArticleByIdResponseDto> GetArticleById(GetArticleByIdRequestDto dto)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ public interface IArticleInteractor
/// <returns>Response DTO</returns>
Task<GetAllArticlesResponseDto> GetAllArticles(GetAllArticlesRequestDto dto);

/// <summary>
/// Get articles with specified author ID
/// </summary>
/// <param name="dto">DTO contract to get articles by author ID</param>
/// <returns>Response DTO</returns>
Task<GetArticlesByAuthorIdResponseDto> GetArticlesByAuthorId(GetArticlesByAuthorIdRequestDto dto);

/// <summary>
/// Get article by ID
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public static IServiceCollection RegisterDomainUseCases(this IServiceCollection
_ = services.AddTransient<IUseCase<Article, UpdateArticleContract>, UpdateArticleUseCase>();
_ = services.AddTransient<IUseCase<ArticleId, DeleteArticleContract>, DeleteArticleUseCase>();
_ = services.AddTransient<IUseCase<List<Article>, GetArticlesByCategoryIdContract>, GetArticlesByCategoryIdUseCase>();
_ = services.AddTransient<IUseCase<List<Article>, GetArticlesByAuthorIdContract>, GetArticlesByAuthorIdUseCase>();

// Auth use cases
_ = services.AddTransient<IUseCase<User, LoginContract>, LoginUseCase>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ internal class ArticleService : BaseService, IArticleService
return await ExecuteUseCase<Article?, GetArticleByIdContract>(contract);
}

public async Task<List<Article>> GetByAuthorId(GetArticlesByAuthorIdContract contract)
{
return await ExecuteUseCase<List<Article>, GetArticlesByAuthorIdContract>(contract);
}

public async Task<List<Article>> GetByCategoryId(GetArticlesByCategoryIdContract contract)
{
return await ExecuteUseCase<List<Article>, GetArticlesByCategoryIdContract>(contract);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using ScienceArchive.BusinessLogic.Interfaces;
using ScienceArchive.Core.Domain.Aggregates.Article;
using ScienceArchive.Core.Repositories;
using ScienceArchive.Core.Services.ArticleContracts;

namespace ScienceArchive.BusinessLogic.ArticleUseCases;

public class GetArticlesByAuthorIdUseCase : IUseCase<List<Article>, GetArticlesByAuthorIdContract>
{
private readonly IArticleRepository _articleRepository;

public GetArticlesByAuthorIdUseCase(IArticleRepository articleRepository)
{
_articleRepository = articleRepository ?? throw new ArgumentNullException(nameof(articleRepository));
}

public async Task<List<Article>> Execute(GetArticlesByAuthorIdContract contract)
{
return await _articleRepository.GetByAuthorId(contract.AuthorId);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using ScienceArchive.Core.Domain.Aggregates.Article;
using ScienceArchive.Core.Domain.Aggregates.Article.ValueObjects;
using ScienceArchive.Core.Domain.Aggregates.Category.ValueObjects;
using ScienceArchive.Core.Domain.Aggregates.User.ValueObjects;
using ScienceArchive.Core.Repositories.Common;

namespace ScienceArchive.Core.Repositories;
Expand All @@ -16,4 +17,11 @@ public interface IArticleRepository : ICrudRepository<ArticleId, Article>
/// <param name="categoryId">Category ID</param>
/// <returns>All articles of specified category</returns>
Task<List<Article>> GetByCategoryId(CategoryId categoryId);

/// <summary>
/// Get articles by author ID
/// </summary>
/// <param name="userId">Author ID</param>
/// <returns>All articles of specified author</returns>
Task<List<Article>> GetByAuthorId(UserId userId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using ScienceArchive.Core.Domain.Aggregates.User.ValueObjects;

namespace ScienceArchive.Core.Services.ArticleContracts;

/// <summary>
/// Contract to get articles by user id
/// </summary>
/// <param name="AuthorId">Author ID</param>
public record GetArticlesByAuthorIdContract(UserId AuthorId);
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ public interface IArticleService
/// <returns>Found article if it exists, otherwise, null</returns>
Task<Article?> GetById(GetArticleByIdContract contract);

/// <summary>
/// Get articles by author ids
/// </summary>
/// <param name="contract">Contract to get articles by author ID</param>
/// <returns>Articles with specified author ID</returns>
Task<List<Article>> GetByAuthorId(GetArticlesByAuthorIdContract contract);

/// <summary>
/// Get articles by category ID
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using ScienceArchive.Core.Domain.Aggregates.Article;
using ScienceArchive.Core.Domain.Aggregates.Article.ValueObjects;
using ScienceArchive.Core.Domain.Aggregates.Category.ValueObjects;
using ScienceArchive.Core.Domain.Aggregates.User.ValueObjects;
using ScienceArchive.Core.Repositories;
using ScienceArchive.Infrastructure.Persistence.Exceptions;
using ScienceArchive.Infrastructure.Persistence.Interfaces;
Expand Down Expand Up @@ -54,7 +55,25 @@ public async Task<List<Article>> GetByCategoryId(CategoryId categoryId)

return articles.Select(_mapper.MapToEntity).ToList();
}


public async Task<List<Article>> GetByAuthorId(UserId userId)
{
var parameters = new DynamicParameters();
parameters.Add("UserId", userId.Value);

var articles = await _connection.QueryAsync<ArticleModel>(
"SELECT * FROM func_get_articles_by_author_id(@UserId)",
parameters,
commandType: CommandType.Text);

if (articles is null)
{
throw new EntityNotFoundException<NewsModel>("Cannot get any article");
}

return articles.Select(_mapper.MapToEntity).ToList();
}

public async Task<Article?> GetById(ArticleId id)
{
var parameters = new DynamicParameters();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public ArticleController(IArticleInteractor articleInteractor)
[HttpGet("by-category/{categoryId}")]
public async Task<Response> GetByCategoryId(string categoryId)
{
if (categoryId is null)
if (string.IsNullOrWhiteSpace(categoryId))
{
throw new ArgumentNullException(nameof(categoryId));
}
Expand All @@ -27,6 +27,19 @@ public async Task<Response> GetByCategoryId(string categoryId)
var result = await _articleInteractor.GetArticlesByCategoryId(dto);
return new SuccessResponse(result);
}

[HttpGet("by-author/{authorId}")]
public async Task<Response> GetByAuthorId(string authorId)
{
if (string.IsNullOrWhiteSpace(authorId))
{
throw new ArgumentNullException(nameof(authorId));
}

var dto = new GetArticlesByAuthorIdRequestDto(authorId);
var result = await _articleInteractor.GetArticlesByAuthorId(dto);
return new SuccessResponse(result);
}

[HttpGet("{id}")]
public async Task<Response> GetById(string id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
"profiles": {
"http": {
"commandName": "Project",
"launchBrowser": false,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:8080",
"environmentVariables": {
Expand Down
18 changes: 14 additions & 4 deletions science-archive-web/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
"src/assets",
"src/manifest.webmanifest"
],
"styles": [
"src/styles.scss"
],
"scripts": []
"scripts": [],
"serviceWorker": true,
"ngswConfigPath": "ngsw-config.json"
},
"configurations": {
"production": {
Expand All @@ -56,7 +59,13 @@
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
"namedChunks": true,
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.development.ts"
}
]
}
},
"defaultConfiguration": "production"
Expand Down Expand Up @@ -90,7 +99,8 @@
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
"src/assets",
"src/manifest.webmanifest"
],
"styles": [
"src/styles.scss"
Expand Down
30 changes: 30 additions & 0 deletions science-archive-web/ngsw-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/index.html",
"/manifest.webmanifest",
"/*.css",
"/*.js"
]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**",
"/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
]
}
}
]
}
Loading

0 comments on commit 4cf2f1d

Please sign in to comment.