Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
48 changes: 24 additions & 24 deletions AStar.Dev.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,29 @@
<Project Path="src/modules/AStar.Dev.FileServices.Common/AStar.Dev.FileServices.Common.csproj" />
<Project Path="src/modules/migrations/AStar.Dev.FilesDb.MigrationService/AStar.Dev.FilesDb.MigrationService.csproj" />
</Folder>
<Folder Name="/src/modules/admin module/">
<Folder Name="/src/modules/admin module/">
<Project Path="src/modules/apis/AStar.Dev.Admin.Api/AStar.Dev.Admin.Api.csproj" />
</Folder>
<Folder Name="/src/modules/db updater module/">
<Project
Path="src/modules/astar-dev-database-updater/AStar.Dev.Database.Updater.Core/AStar.Dev.Database.Updater.Core.csproj"/>
<Project
Path="src/modules/astar-dev-database-updater/AStar.Dev.Database.Updater/AStar.Dev.Database.Updater.csproj"/>
</Folder>
<Folder Name="/src/modules/file classifications module/">
</Folder>
<Folder Name="/src/modules/db updater module/">
<Project Path="src/modules/astar-dev-database-updater/AStar.Dev.Database.Updater.Core/AStar.Dev.Database.Updater.Core.csproj" />
<Project Path="src/modules/astar-dev-database-updater/AStar.Dev.Database.Updater/AStar.Dev.Database.Updater.csproj" />
</Folder>
<Folder Name="/src/modules/file classifications module/">
<Project Path="src/modules/apis/AStar.Dev.Files.Classifications.Api/AStar.Dev.Files.Classifications.Api.csproj" />
</Folder>
<Folder Name="/src/modules/files module/">
<Project Path="src/modules/apis/AStar.Dev.Files.Api/AStar.Dev.Files.Api.csproj"/>
</Folder>
<Folder Name="/src/modules/images module/">
</Folder>
<Folder Name="/src/modules/files module/">
<Project Path="src/modules/apis/AStar.Dev.Files.Api/AStar.Dev.Files.Api.csproj" />
</Folder>
<Folder Name="/src/modules/images module/">
<Project Path="src/modules/apis/AStar.Dev.Images.Api/AStar.Dev.Images.Api.csproj" />
</Folder>
<Folder Name="/src/modules/todo module/">
</Folder>
<Folder Name="/src/modules/todo module/">
<Project Path="src/modules/apis/AStar.Dev.ToDo.Api/AStar.Dev.ToDo.Api.csproj" />
</Folder>
<Folder Name="/src/modules/usage module/">
<Project Path="src/nuget-packages/AStar.Dev.Api.Usage.Sdk/AStar.Dev.Api.Usage.Sdk.csproj"/>
<Project Path="src\nuget-packages\AStar.Dev.Usage.Api.Client.SDK\AStar.Dev.Usage.Api.Client.SDK.csproj"
Type="Classic C#"/>
</Folder>
<Folder Name="/src/modules/usage module/">
<Project Path="src/nuget-packages/AStar.Dev.Api.Usage.Sdk/AStar.Dev.Api.Usage.Sdk.csproj" />
<Project Path="src\nuget-packages\AStar.Dev.Usage.Api.Client.SDK\AStar.Dev.Usage.Api.Client.SDK.csproj" Type="C#" />
</Folder>
<Folder Name="/src/nuget-packages/">
<Project Path="src/nuget-packages/AStar.Dev.Api.HealthChecks/AStar.Dev.Api.HealthChecks.csproj" />
<Project Path="src/nuget-packages/AStar.Dev.AspNet.Extensions/AStar.Dev.AspNet.Extensions.csproj" />
Expand All @@ -65,6 +62,10 @@
<Project Path="src/nuget-packages/AStar.Dev.Test.Helpers/AStar.Dev.Test.Helpers.csproj" />
<Project Path="src/nuget-packages/AStar.Dev.Utilities/AStar.Dev.Utilities.csproj" />
</Folder>
<Folder Name="/src/source-generators/">
<Project Path="src/source-generators/AStar.Dev.SourceGenerators/AStar.Dev.SourceGenerators.csproj" />
<Project Path="src\source-generators\AStar.Dev.Annotations\AStar.Dev.Annotations.csproj" Type="Classic C#" />
</Folder>
<Folder Name="/src/uis/">
<Project Path="src/uis/AStar.Dev.Web/AStar.Dev.Web.csproj" />
</Folder>
Expand Down Expand Up @@ -93,9 +94,8 @@
<Project Path="test/modules/apis/AStar.Dev.Images.Api.Tests.Integration/AStar.Dev.Images.Api.Tests.Integration.csproj" />
<Project Path="test/modules/apis/AStar.Dev.Images.Api.Tests.Unit/AStar.Dev.Images.Api.Tests.Unit.csproj" />
</Folder>
<Folder Name="/test/modules/file classifications module/">
<Project
Path="test/modules/apis/AStar.Dev.Files.Classifications.Api.Tests.Unit/AStar.Dev.Files.Classifications.Api.Tests.Unit.csproj"/>
<Folder Name="/test/modules/file classifications module/">
<Project Path="test/modules/apis/AStar.Dev.Files.Classifications.Api.Tests.Unit/AStar.Dev.Files.Classifications.Api.Tests.Unit.csproj" />
</Folder>
<Folder Name="/test/nuget-packages/">
<Project Path="test/nuget-packages/AStar.Dev.Api.HealthChecks.Tests.Unit/AStar.Dev.Api.HealthChecks.Tests.Unit.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,14 @@ namespace AStar.Dev.AppHost.Configurations;

public static class DatabaseUpdaterApiProjectConfigurator
{
public record DatabaseUpdaterApiProjectConfig(string ProjectName);

public static DatabaseUpdaterApiProjectConfig GetConfig() => new(AspireConstants.Services.DatabaseUpdater);

public static void Configure(
IDistributedApplicationBuilder builder,
IResourceBuilder<SqlServerDatabaseResource> filesDb,
IResourceBuilder<ProjectResource> migrations,
IResourceBuilder<SqlServerServerResource> sqlServer,
IResourceBuilder<RabbitMQServerResource> rabbitMq)
{
DatabaseUpdaterApiProjectConfig config = GetConfig();
_ = builder.AddProject<AStar_Dev_Database_Updater>(config.ProjectName)
_ = builder.AddProject<AStar_Dev_Database_Updater>(AspireConstants.Services.DatabaseUpdater)
.WithReference(filesDb)
.WaitFor(filesDb)
.WithReference(migrations)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static void AddApplicationProjects(this IDistributedApplicationBuilder bu
IResourceBuilder<SqlServerDatabaseResource> astarDb = sqlServer.AddDatabase(AspireConstants.Sql.AStarDb);
IResourceBuilder<ProjectResource> migrations = MigrationsConfigurator.Configure(builder, astarDb, sqlServer, sqlSaUserPassword, sqlAdminUserPassword, sqlFilesUserPassword, sqlUsageUserPassword);
IResourceBuilder<RabbitMQServerResource> rabbitMq = RabbitMqConfigurator.Configure(builder);
DatabaseUpdaterApiProjectConfigurator.Configure(builder, astarDb, migrations, sqlServer, rabbitMq);
//DatabaseUpdaterApiProjectConfigurator.Configure(builder, astarDb, migrations, sqlServer, rabbitMq);

UiProjectConfigurator.Configure(builder, astarDb, rabbitMq);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static IResourceBuilder<SqlServerServerResource> Configure(IDistributedAp
SqlServerConfig config = GetConfig();
return builder.AddSqlServer(config.ServerName, sqlPassword, config.Port)
.WithLifetime(ContainerLifetime.Persistent)
//.WithDataBindMount(sqlMountDirectory)
.WithDataBindMount("/home/jason/databases")
.WithExternalHttpEndpoints();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Microsoft.EntityFrameworkCore;

namespace AStar.Dev.Files.Classifications.Api.Endpoints.FileClassifications.V1;

/// <summary>
/// Provides an extension method to join file classifications with their parent classifications.
/// </summary>
public static class FileClassificationJoined
{
/// <summary>
/// Joins file classifications with their associated parent classifications using a left join approach.
/// Each file classification is paired with its parent classification, if available.
/// </summary>
/// <param name="query">The database queryable set of file classifications.</param>
/// <returns>An <see cref="IQueryable{FileClassifications}"/> containing the joined file classification and parent classification data.</returns>
public static IQueryable<FileClassifications> JoinFileClassificationsToParents(this DbSet<AStar.Dev.Infrastructure.FilesDb.Models.FileClassification> query)
=> query.AsNoTracking()
.GroupJoin(
query,
fc => fc.ParentId,
p => p.Id,
(fc, parents) => new { fc, parents }
)
.SelectMany(x => x.parents.DefaultIfEmpty(), (x, p) => new FileClassifications( x.fc, p ));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace AStar.Dev.Files.Classifications.Api.Endpoints.FileClassifications.V1;

/// <summary>
/// Represents the aggregation of a file classification and its optional parent file classification.
/// This record is utilized to handle hierarchical relationships between file classifications,
/// where a file classification can have a parent classification for organizational purposes.
/// </summary>
/// <param name="FileClassification">
/// The primary file classification data, representing a specific classification instance.
/// </param>
/// <param name="Parent">
/// The optional parent classification, indicating its hierarchical relationship to the primary
/// file classification. A null value signifies no parent classification.
/// </param>
public record FileClassifications(Infrastructure.FilesDb.Models.FileClassification FileClassification, Infrastructure.FilesDb.Models.FileClassification? Parent);
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace AStar.Dev.Files.Classifications.Api.Endpoints.FileClassifications.V1;
/// The object supports HTTP GET operation to access the required endpoint.
/// </summary>
[UsedImplicitly]
public record GetFileClassificationRequest(int CurrentPage = 1, int ItemsPerPage = 10) : IEndpointName
public record GetFileClassificationRequest(int CurrentPage = 1, int ItemsPerPage = 10) : IEndpointName,IPagingParameters
{
/// <inheritdoc />
public string Name => EndpointConstants.GetFileClassificationsGroupName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,29 @@ public async Task<IReadOnlyCollection<GetFileClassificationsResponse>> HandleAsy
GetFileClassificationRequest fileClassifications, FilesContext filesContext,
CancellationToken cancellationToken)
{
if(fileClassifications.ItemsPerPage > 50) fileClassifications = fileClassifications with { ItemsPerPage = 50 };
var pagingParams = PagingParams.CreateValid(fileClassifications);

List<GetFileClassificationsResponse> classifications = await filesContext.FileClassifications
.OrderBy(fc => fc.Name)
.Skip(fileClassifications.CurrentPage - 1).Take(fileClassifications.ItemsPerPage)
.Select(fc => new GetFileClassificationsResponse(fc.Id, fc.Name, fc.IncludeInSearch, fc.Celebrity))
return await filesContext.FileClassifications
.AsNoTracking()
.GroupJoin(
filesContext.FileClassifications.AsNoTracking(),
fc => fc.ParentId,
p => p.Id,
(fc, parents) => new { fc, parents }
)
.SelectMany(x => x.parents.DefaultIfEmpty(), (x, p) => new { x.fc, p })
.OrderBy(x => x.fc.Name)
.Skip(pagingParams.SkipValue)
.Take(pagingParams.PageSize)
.Select(x => new GetFileClassificationsResponse(
x.fc.Id,
x.fc.Name,
x.fc.IncludeInSearch,
x.fc.Celebrity,
x.fc.ParentId,
x.p != null ? x.p.Name : null,
x.fc.SearchLevel
))
.ToListAsync(cancellationToken);

return classifications;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ namespace AStar.Dev.Files.Classifications.Api.Endpoints.FileClassifications.V1;
/// <summary>
/// Response model for file classification data
/// </summary>
public record GetFileClassificationsResponse(Guid Id, string Name, bool IncludeInSearch, bool Celebrity);
public record GetFileClassificationsResponse(Guid Id, string Name, bool IncludeInSearch, bool Celebrity, Guid? ParentId, string? Parent = null, int SearchLevel = 2);
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace AStar.Dev.Files.Classifications.Api.Endpoints.FileClassifications.V1;

/// <summary>
/// Defines the parameters necessary to support pagination functionality, including the current page
/// and the number of items per page.
/// Objects implementing this interface provide a standardized way to manage paginated data retrieval.
/// </summary>
public interface IPagingParameters
{
/// <summary>
/// Gets the current page number for pagination purposes.
/// This property specifies which page of results should be retrieved.
/// </summary>
int CurrentPage { get; }

/// <summary>
/// Gets the number of items to be displayed per page in a paginated request.
/// </summary>
int ItemsPerPage { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace AStar.Dev.Files.Classifications.Api.Endpoints.FileClassifications.V1;

internal sealed class PagingParams
{
private PagingParams(int pageSize, int skipValue)
{
PageSize = pageSize;
SkipValue = skipValue;
}

public int PageSize { get; }

public int SkipValue { get; }

public static PagingParams CreateValid(IPagingParameters pagingParams)
{
var pageSize = pagingParams.ItemsPerPage <= 0
? 10
: (pagingParams.ItemsPerPage > 50 ? 50 : pagingParams.ItemsPerPage);
var pageIndex = pagingParams.CurrentPage <= 0 ? 1 : pagingParams.CurrentPage;
var skip = (pageIndex - 1) * pageSize;

return new PagingParams(pageSize, skip);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
/// <summary>
/// Represents a classification of files, containing details about name, search level, parent classification, and flags for celebrity status or search inclusion.
/// </summary>
public record FileClassification(Guid Id, int SearchLevel, Guid? ParentId, string Name, bool Celebrity, bool IncludeInSearch);
public record FileClassification(Guid Id, int SearchLevel, string Name, Guid? ParentId, string? ParentName, bool Celebrity, bool IncludeInSearch);
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ public class FileClassificationsService2 : IFileClassificationsService2
/// </summary>
/// <returns>A collection of file classification names.</returns>
public async Task<IList<FileClassification>> GetFileClassificationsAsync()
=> await _context.FileClassifications.Select(fc => new FileClassification(fc.Id, fc.SearchLevel, fc.ParentId, fc.Name, fc.Celebrity, fc.IncludeInSearch)).ToListAsync();
=> await _context.FileClassifications
.Select(fc => new FileClassification(fc.Id, fc.SearchLevel, fc.Name, fc.ParentId, fc.ParentId.ToString(), fc.Celebrity, fc.IncludeInSearch))
.ToListAsync();
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
},
"databaseUpdaterConfiguration": {
"rootDirectory": "/home/jason/Documents/Pictures/_lookat/",
"mappingsFilePath": "/home/jason/Documents/Mappings.csv",
"mappingsFilePath": "/home/jason/Documents/File-Mappings.csv",
"softDeleteScheduledTime": "02:00",
"hardDeleteScheduledTime": "03:00",
"newFilesScheduledTime": "04:00",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<AnalysisLevel>latest-recommended</AnalysisLevel>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>

<PropertyGroup>
Expand Down Expand Up @@ -54,6 +55,8 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\source-generators\AStar.Dev.Annotations\AStar.Dev.Annotations.csproj" />
<ProjectReference Include="..\..\source-generators\AStar.Dev.SourceGenerators\AStar.Dev.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\AStar.Dev.Infrastructure\AStar.Dev.Infrastructure.csproj"/>
<ProjectReference Include="..\AStar.Dev.Technical.Debt.Reporting\AStar.Dev.Technical.Debt.Reporting.csproj"/>
<ProjectReference Include="..\AStar.Dev.Utilities\AStar.Dev.Utilities.csproj"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using AStar.Dev.Annotations;

namespace AStar.Dev.Infrastructure.FilesDb.Models;

/// <summary>
/// Defines the FileId
/// </summary>
public record struct FileId()
[StrongId]
public partial record struct FileId()
{
/// <summary>The value of the File ID</summary>
public Guid Value { get; set; } = Guid.CreateVersion7();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

</Project>
40 changes: 40 additions & 0 deletions src/source-generators/AStar.Dev.Annotations/StrongIdAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;

namespace AStar.Dev.Annotations;

/// <summary>
/// Represents an attribute that can be used to mark a struct as a strong identifier.
/// </summary>
/// <remarks>
/// This attribute is used to annotate structures with a specific identifier type, typically
/// to signify that the struct is a strongly typed id. The default identifier type is a GUID.
/// </remarks>
/// <param name="idType">
/// The type of the identifier associated with the struct. By default, it is "System.Guid".
/// </param>
/// <param name="guidV7">
/// Indicates whether the GUID used as the identifier for the struct conforms to the version 7 GUID format.
/// </param>
[AttributeUsage(AttributeTargets.Struct)]
public sealed class StrongIdAttribute(string idType = "System.Guid", bool guidV7 = true) : Attribute
{
/// <summary>
/// Gets the type of the identifier associated with a struct marked by the <see cref="StrongIdAttribute"/>.
/// </summary>
/// <remarks>
/// This property returns the string name of the identifier type. By default, it is "System.Guid".
/// The identifier type specifies the type used as an identifier for the struct.
/// </remarks>
public string IdType { get; } = idType;

/// <summary>
/// Indicates whether the GUID used as the identifier for a struct marked by the <see cref="StrongIdAttribute"/>
/// conforms to the version 7 GUID format.
/// </summary>
/// <remarks>
/// Version 7 GUIDs are designed to facilitate time-based sorting and are a newer standard
/// compared to the traditional random GUIDs (version 4). When this property is set to true,
/// the identifier adopts the version 7 format.
/// </remarks>
public bool GuidV7 { get; } = guidV7;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IncludeBuildOutput>false</IncludeBuildOutput>
<IsRoslynComponent>true</IsRoslynComponent>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" PrivateAssets="all"/>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="4.14.0" PrivateAssets="all"/>
</ItemGroup>

</Project>
Loading
Loading