Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ae20c35
🚧 Add API structure
ColdCoffeeStudio Dec 11, 2025
dd39ae3
🚧 Add API related DTO
ColdCoffeeStudio Dec 12, 2025
299341e
🚧 Add services interaces
ColdCoffeeStudio Dec 12, 2025
91980c9
🐛 Fix wrong error type in AnswerDto.cs
ColdCoffeeStudio Dec 12, 2025
4b0427a
🤡 Mock EncyclopediaSearchService for test purposes
ColdCoffeeStudio Dec 12, 2025
8d565e4
🚧 Link EncyclopediaSearch to its controller
ColdCoffeeStudio Dec 12, 2025
21a2790
♻️ Refactor entities to match needs
ColdCoffeeStudio Dec 15, 2025
76b3e1b
✨ Add EncyclopediaList entity
ColdCoffeeStudio Dec 15, 2025
3a93702
✨ Add AnswerListDto
ColdCoffeeStudio Dec 15, 2025
388772c
✨ Add Create method to Scribe.cs
ColdCoffeeStudio Dec 16, 2025
6cccbe0
✨ Add api/v1/encyclopedia/filters API implementation
ColdCoffeeStudio Dec 16, 2025
3815761
🎨 Clean EncyclopediaSearchService
ColdCoffeeStudio Dec 16, 2025
dadc49a
🐛 Add missing tags attribute in Annotation entity
ColdCoffeeStudio Dec 18, 2025
996d5dc
✨ Improve security with database returned entities
ColdCoffeeStudio Dec 18, 2025
135a0bd
🐛 Fix InvalidFolder method
ColdCoffeeStudio Dec 19, 2025
8f838e7
✨ Add content table related Entities
ColdCoffeeStudio Dec 19, 2025
45eb50b
♻️ Change notes attribute to List
ColdCoffeeStudio Dec 19, 2025
6a2139b
✨ Add api/v1/encyclopedia/content-table API implementation
ColdCoffeeStudio Dec 19, 2025
8442b45
✨ Add production ContentTableService link
ColdCoffeeStudio Dec 19, 2025
c0a5098
✏️ Rename application name
ColdCoffeeStudio Dec 19, 2025
839775e
🔥 Remove unused import
ColdCoffeeStudio Dec 19, 2025
0f3f2a1
🔥 Remove unused import
ColdCoffeeStudio Dec 19, 2025
8e499e0
🐛 Fix incorrect namespace
ColdCoffeeStudio Dec 19, 2025
6ec2e25
🐛 Fix missing dependency
ColdCoffeeStudio Dec 19, 2025
a5b80e2
🔥 Clean /api/v1/content-table fetching
ColdCoffeeStudio Dec 19, 2025
18cc654
🐛 Fix incorrect types in AnnotationDto
ColdCoffeeStudio Dec 19, 2025
7f6856a
✨ Add api/v1/annotation API implementation
ColdCoffeeStudio Dec 19, 2025
532042b
🐛 Fix NullPointerException when Annotation is not found
ColdCoffeeStudio Dec 27, 2025
2ab0a6d
✨ Add EncyclopediaNotFound Error
ColdCoffeeStudio Dec 27, 2025
aa72abd
♻️ Refactor Content table fetching
ColdCoffeeStudio Dec 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using Application.Common.Abstractions.Messaging;
using Domain.Entities;

namespace Application.AnnotationOperations.Queries.FetchAnnotationFromEncyclopediaId;

public sealed record FetchAnnotationFromEncyclopediaIdQuery(int EncyclopediaId): IQuery<AnnotationList>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Application.Common.Abstractions.Messaging;
using Application.Common.Databases;
using Domain.Entities;
using Domain.Shared;
using Microsoft.Extensions.Logging;

namespace Application.AnnotationOperations.Queries.FetchAnnotationFromEncyclopediaId;

public sealed class FetchAnnotationFromEncyclopediaIdQueryHandler(
IAnnotationRepository annotationRepository,
IEncyclopediaRepository encyclopediaRepository,
ILogger<FetchAnnotationFromEncyclopediaIdQueryHandler> logger) : IQueryHandler<FetchAnnotationFromEncyclopediaIdQuery, AnnotationList>
{
public async Task<Result<AnnotationList>> Handle(FetchAnnotationFromEncyclopediaIdQuery request, CancellationToken cancellationToken)
{
return await annotationRepository.FetchAnnotationFromEncyclopedia(request.EncyclopediaId, cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using Application.Common.Abstractions.Messaging;
using Domain.Entities;

namespace Application.AnnotationOperations.Queries.FetchAnnotationFromId;

public sealed record FetchAnnotationFromIdQuery(int id): IQuery<Annotation>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Application.Common.Abstractions.Messaging;
using Application.Common.Databases;
using Domain.Entities;
using Domain.Shared;

namespace Application.AnnotationOperations.Queries.FetchAnnotationFromId;

public class FetchAnnotationFromIdQueryHandler(
IAnnotationRepository repository
): IQueryHandler<FetchAnnotationFromIdQuery, Annotation>
{
public async Task<Result<Annotation>> Handle(FetchAnnotationFromIdQuery request,
CancellationToken cancellationToken)
{
return await repository.FetchAnnotationFromId(request.id, cancellationToken);
}
}
10 changes: 10 additions & 0 deletions Application/Common/Databases/IAnnotationRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Domain.Entities;
using Domain.Shared;

namespace Application.Common.Databases;

public interface IAnnotationRepository
{
Task<Result<AnnotationList>> FetchAnnotationFromEncyclopedia(int encyclopediaId, CancellationToken cancellationToken);
Task<Result<Annotation>> FetchAnnotationFromId(int id, CancellationToken cancellationToken);
}
9 changes: 9 additions & 0 deletions Application/Common/Databases/IEncyclopediaRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Domain.Entities;
using Domain.Shared;

namespace Application.Common.Databases;

public interface IEncyclopediaRepository
{
Task<Result<EncyclopediaList>> FetchEncyclopedia(CancellationToken cancellationToken);
}
6 changes: 6 additions & 0 deletions Application/Common/Databases/IThemeRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Application.Common.Databases;

public class IThemeRepository
{

}
24 changes: 24 additions & 0 deletions Application/Common/Mappers/AnnotationToDtoMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Application.DTO;
using Domain.Entities;

namespace Application.Common.Mappers;

public class AnnotationToDtoMapper
{
public AnnotationDto Map(Annotation annotation)
{
AnnotationDto annotationDto = new AnnotationDto(
annotation.Id,
annotation.Title,
annotation.StartPage,
annotation.EndPage,
annotation.ContentUrl,
annotation.Tags,
annotation.Date,
annotation.Theme.Id,
annotation.Encyclopedia.Id
);

return annotationDto;
}
}
25 changes: 25 additions & 0 deletions Application/Common/Mappers/ContentTableToDtoMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Application.DTO;
using Domain.Entities;
using Domain.Shared;

namespace Application.Common.Mappers;

public class ContentTableToDtoMapper
{
public List<IDto> Map(ContentTable contentTable)
{
List<IDto> contentTableDto = new List<IDto>();

foreach (ContentTableEntry entry in contentTable.Entries)
{
List<NoteIdDto> notesDto = new List<NoteIdDto>();
foreach (Annotation note in entry.Notes)
{
notesDto.Add(new NoteIdDto(note.Id, note.Title));
}
contentTableDto.Add(new ContentTableEntryDto(entry.Id, entry.ThemeName, notesDto));
}

return contentTableDto;
}
}
21 changes: 21 additions & 0 deletions Application/Common/Mappers/EncyclopediaListAnswerListDtoMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Application.DTO;
using Domain.Entities;
using Domain.Shared;

namespace Application.Common.Mappers;

public class EncyclopediaListAnswerListDtoMapper
{
public AnswerListDto Map(EncyclopediaList list)
{
List<IDto> encyclopediaDtos = new List<IDto>();
EncyclopediaToDtoMapper mapper = new EncyclopediaToDtoMapper();

foreach (Encyclopedia encyclopedia in list.List)
{
encyclopediaDtos.Add(mapper.Map(encyclopedia));
}

return new AnswerListDto(true, encyclopediaDtos, Error.Empty());
}
}
19 changes: 19 additions & 0 deletions Application/Common/Mappers/EncyclopediaToDtoMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Application.DTO;
using Domain.Entities;

namespace Application.Common.Mappers;

public class EncyclopediaToDtoMapper
{
public EncyclopediaDto Map(Encyclopedia encyclopedia)
{
EncyclopediaDto encyclopediaDto = new EncyclopediaDto(
encyclopedia.Id,
encyclopedia.Title,
encyclopedia.Scribe.Id,
encyclopedia.Scribe.Name
);

return encyclopediaDto;
}
}
6 changes: 3 additions & 3 deletions Application/DTO/AnnotationDto.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
namespace Application.DTO;

public record AnnotationDto(
Guid Id,
int Id,
string Title,
int StartPage,
int LastPage,
string ContentUrl,
string Tags,
DateOnly Date,
Guid ThemeId,
Guid EncyclopediaId
int ThemeId,
int EncyclopediaId
): IDto;
5 changes: 5 additions & 0 deletions Application/DTO/AnswerDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Domain.Shared;

namespace Application.DTO;

public record AnswerDto(bool Success, IDto Value, Error error);
5 changes: 5 additions & 0 deletions Application/DTO/AnswerListDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Domain.Shared;

namespace Application.DTO;

public record AnswerListDto(bool Success, List<IDto> Value, Error error);
3 changes: 3 additions & 0 deletions Application/DTO/ContentTableEntryDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Application.DTO;

public sealed record ContentTableEntryDto(int Id, string ThemeName, List<NoteIdDto> notes): IDto;
5 changes: 3 additions & 2 deletions Application/DTO/EncyclopediaDto.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
namespace Application.DTO;

public record EncyclopediaDto(
Guid Id,
int Id,
string Title,
Guid ScribeId
Guid ScribeId,
string ScribeName
): IDto;
5 changes: 5 additions & 0 deletions Application/DTO/IDto.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
using System.Text.Json.Serialization;

namespace Application.DTO;

[JsonDerivedType(typeof(EncyclopediaDto), typeDiscriminator: "encyclopedia")]
[JsonDerivedType(typeof(ContentTableEntryDto), typeDiscriminator: "contentTableEntry")]

public interface IDto
{

Expand Down
3 changes: 3 additions & 0 deletions Application/DTO/NoteIdDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Application.DTO;

public sealed record NoteIdDto(int Id, string Title): IDto;
3 changes: 3 additions & 0 deletions Application/DTO/NoteInformationsDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Application.DTO;

public sealed record NoteInformationsDto(int Id, string ContentUrl, int StartPage, int EndPage, string Tags, DateOnly Date): IDto;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using Application.Common.Abstractions.Messaging;
using Domain.Entities;

namespace Application.EncyclopediaOperations.Queries.FetchEncyclopedia;

public sealed record FetchEncyclopediaQuery(): IQuery<EncyclopediaList>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Application.Common.Abstractions.Messaging;
using Application.Common.Databases;
using Domain.Entities;
using Domain.Shared;
using Microsoft.Extensions.Logging;

namespace Application.EncyclopediaOperations.Queries.FetchEncyclopedia;

public sealed class FetchEncyclopediaQueryHandler(
IEncyclopediaRepository repository,
ILogger<FetchEncyclopediaQueryHandler> logger) : IQueryHandler<FetchEncyclopediaQuery, EncyclopediaList>
{
public async Task<Result<EncyclopediaList>> Handle(FetchEncyclopediaQuery request, CancellationToken cancellationToken)
{
Result<EncyclopediaList> result = await repository.FetchEncyclopedia(cancellationToken);

return new Result<EncyclopediaList>(result.Value, result.Error, result.Succeeded);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Application.AnnotationOperations.Queries.FetchAnnotationFromId;
using Application.Common.Mappers;
using Application.DTO;
using Domain.Entities;
using Domain.Errors;
using Domain.Shared;
using MediatR;
using Microsoft.Extensions.Logging;

namespace Application.Services.AnnotationInformation;

public class AnnotationInformationService(ISender sender, ILogger<AnnotationInformationService> logger): IAnnotationInformationService
{
public async Task<AnswerDto> HandleAnnotationInformationAsync(int id, CancellationToken cancellationToken)
{
AnswerDto result;
AnnotationToDtoMapper mapper = new AnnotationToDtoMapper();
AnnotationInformationServiceErrors errors = new AnnotationInformationServiceErrors();

Result<Annotation> annotation = await sender.Send(new FetchAnnotationFromIdQuery(id), cancellationToken);

return annotation.Succeeded
? new AnswerDto(true, mapper.Map(annotation.Value), Error.Empty())
: new AnswerDto(false, mapper.Map(Annotation.Empty()), annotation.Error);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Application.DTO;

namespace Application.Services.AnnotationInformation;

public interface IAnnotationInformationService
{
Task<AnswerDto> HandleAnnotationInformationAsync(int annotationId, CancellationToken cancellationToken);
}
62 changes: 62 additions & 0 deletions Application/Services/ContentTableSearch/ContentTableService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Application.AnnotationOperations.Queries.FetchAnnotationFromEncyclopediaId;
using Application.Common.Mappers;
using Application.DTO;
using Domain.Entities;
using Domain.Errors;
using Domain.Shared;
using MediatR;
using Microsoft.Extensions.Logging;

namespace Application.Services.ContentTableSearch;

public class ContentTableService (ISender sender, ILogger<ContentTableService> logger): IContentTableService
{
private readonly ContentTableServiceErrors _errors = new();
private readonly ContentTableToDtoMapper _mapper = new();

public async Task<AnswerListDto> HandleContentTableAsync(int encyclopediaId, CancellationToken cancellationToken)
{
Result<AnnotationList> annotationsList = await sender.Send(new FetchAnnotationFromEncyclopediaIdQuery(encyclopediaId), cancellationToken);

return annotationsList.Succeeded
? BuildContentTable(annotationsList.Value)
: new AnswerListDto(false, new List<IDto>(), annotationsList.Error);
}

private AnswerListDto BuildContentTable(AnnotationList annotationsList)
{
List<ContentTableEntry> contentTableEntries = [];
List<Annotation> annotations = annotationsList.Annotations;
List<Theme> themes = annotations
.Select(a => a.Theme)
.Distinct()
.ToList();

foreach (Annotation annotation in annotations)
{
Theme theme = annotation.Theme;

List<Annotation> tmpNotes = annotations
.Where(a => a.Theme.Id == theme.Id)
.ToList();

Result<ContentTableEntry> tmpContentTableEntry =
ContentTableEntry.Create(theme.Id, theme.Name, tmpNotes);

if (tmpContentTableEntry.Failed)
{
return new AnswerListDto(false, new List<IDto>(), _errors.ContentTableEntryCreationError(tmpContentTableEntry.Error));
}

contentTableEntries.Add(tmpContentTableEntry.Value);
}

Result<ContentTable> tmpContentTable = ContentTable.Create(contentTableEntries);

AnswerListDto result = tmpContentTable.Succeeded
? new AnswerListDto(true, _mapper.Map(tmpContentTable.Value), Error.Empty())
: new AnswerListDto(false, new List<IDto>(), _errors.ContentTableCreationError(tmpContentTable.Error));

return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Application.DTO;

namespace Application.Services.ContentTableSearch;

public interface IContentTableService
{
Task<AnswerListDto> HandleContentTableAsync(int encyclopediaId, CancellationToken cancellationToken);
}
Loading